Date: Thu Mar 26 04:36:03 2020
Scientist: Ran Yin
Sequencing (Waksman): Dibyendu Kumar
Statistics: Davit Sargsyan
Principal Investigator: Ah-Ng Kong

# Taxonomic Ranks:
# **K**ing **P**hillip **C**an n**O**t **F**ind **G**reen **S**ocks
# * Kingdom                
# * Phylum                    
# * Class                   
# * Order                   
# * Family     
# * Genus     
# * Species  
# options(stringsAsFactors = FALSE,
#         scipen = 999)
# # Increase mmemory size to 64 Gb----
# invisible(utils::memory.limit(65536))
# str(knitr::opts_chunk$get())
# # NOTE: the below does not work!
# knitr::opts_chunk$set(echo = FALSE, 
#                       message = FALSE,
#                       warning = FALSE,
#                       error = FALSE)
# require(knitr)
# require(kableExtra)
# require(shiny)
require(phyloseq)
Loading required package: phyloseq
require(data.table)
Loading required package: data.table
data.table 1.12.2 using 18 threads (see ?getDTthreads).  Latest news: r-datatable.com
require(ggplot2)
Loading required package: ggplot2
require(plotly)
Loading required package: plotly

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
require(DT)
Loading required package: DT
require(lmerTest)
Loading required package: lmerTest
Loading required package: lme4
Loading required package: Matrix

Attaching package: ‘lmerTest’

The following object is masked from ‘package:lme4’:

    lmer

The following object is masked from ‘package:stats’:

    step
require(nnet)
Loading required package: nnet
source("source/functions_may2019.R")
# On Windows set multithread=FALSE----
mt <- TRUE

1 Introduction

C57BL/6 wild-type (WT) and Nrf-2 double-knock-out (KO -/-) mice were given 2-week microbiome stabilization process using AIN93M diet and 8 more weeks to treat with either AIN93M or AIN93M 5% PEITC diet. Fecal samples were collected weekly, immediately frozen in liquid nitrogen and stored at -80oC. Serum, cecal, colon epithelial and whole colon tissues at week 10 were also collected for further analyses. Baseline, week 1 and 4 fecal samples were selected for 16s rRNA sequencing.

This document examines results from the WT mice samples.

We will attampt to answer the following questions:
1. Did microbiome change over time?
2. Was microbiome affected by diet?
3. Was there a difference between the KO and WT?
4. If there was a change in microbiome composition, what functional changes did it carry? What are the essential functions of the bacteria affected by the treatment and how can this be shown in vivo (metabolites, inflammation markers, etc.)?

2 Data preprocessing

2.1 Raw Data

FastQ files were downloaded from this Rutgers Box location. A total of 144 files (2 per sample, pair-ended) and a pair of undetermined reads were downloaded.

2.2 Script

This script (nrf2ubiome_dada2_sep2019_v1.Rmd) was developed using DADA2 Pipeline Tutorial (1.12) with tips and tricks from the University of Maryland Shool of Medicine Institute for Genome Sciences (IGS) Microbiome Analysis Workshop (April 8-11, 2019). The output of the DADA2 script (data_may2019/ps_sep2019.RData) is explored in this document.

3 Meta data: sample description

# Load data----
# Counts
load("data_sep2019/ps_sep2019.RData")
# Taxonomy
load("data_sep2019/taxa.RData")
taxa <- data.table(seq16s = rownames(taxa),
                   taxa)

NOTE: correction to the meta-data! (11/15/2019)

correct_samples <- fread("data_sep2019/16s metadata Sep-2019.csv")
ps_sep2019@sam_data$DSS <- correct_samples$DSS

4 Samples

ps_sep2019@sam_data$Genotype_Week <- paste(ps_sep2019@sam_data$genotype,
                                           ps_sep2019@sam_data$time,
                                           sep = "_")
ps_sep2019@sam_data$ID <- factor(paste0(ps_sep2019@sam_data$mice_num,
                                        ps_sep2019@sam_data$cage))
ps_sep2019@sam_data$TREATMENT <- paste0(ps_sep2019@sam_data$DSS,
                                        ps_sep2019@sam_data$PEITC,
                                        ps_sep2019@sam_data$cranberry)
ps_sep2019@sam_data$TREATMENT <- factor(ps_sep2019@sam_data$TREATMENT,
                                        levels = c("000",
                                                   "100",
                                                   "110",
                                                   "101"),
                                        labels = c("Naive",
                                                   "DSS",
                                                   "DSS+PEITC",
                                                   "DSS+Cranberry"))
samples <- ps_sep2019@sam_data
datatable(samples,
          options = list(pageLength = nrow(samples)))

5 Prune data

The OTUs were mapped to Bacteria (96.07%), Eukaryota (2.95%) and Archea (0.03%) kingdoms, and 75 OTUs (0.95%) undefined.

The total of 7,867 unique sequences were found. Out of those, 7,558 were mapped to bacterial genomes.

dim(ps_sep2019@otu_table@.Data)

# Remove OTU not mapped to Bacteria
ps0 <- subset_taxa(ps_sep2019, 
                   Kingdom == "Bacteria")
dim(ps0@otu_table@.Data)

Out of the 7,558 OTUs 7,247 belonged to 12 Phyla. 311 of the OTUs (or 4.11% of bacterial OTUs) could not be mapped to a phylum.

t2 <- data.table(table(tax_table(ps0)[, "Phylum"],
                                  exclude = NULL))
t2$V1[is.na(t2$V1)] <- "Unknown"
setorder(t2, -N)
t2[, pct := N/sum(N)]
setorder(t2, -N)
colnames(t2) <- c("Phylum",
                  "Number of OTUs",
                  "Percent of OTUs")
datatable(t2,
          rownames = FALSE,
          caption = "Number of Bacterial OTUs by Phylum",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t2))) %>%
  formatCurrency(columns = 2,
                 currency = "",
                 mark = ",",
                 digits = 0) %>%
  formatPercentage(columns = 3,
                   digits = 2)

6 OTU table (first 10 rows)

7 Total counts per sample (i.e. sequencing depth)

t1 <- colSums(otu[, 7:ncol(otu)])
t1 <- data.table(SAMPLE_NAME = names(t1),
                 Total = t1)

t2 <- data.table(SAMPLE_NAME = rownames(samples),
                 ID = samples$ID,
                 CAGE = samples$cage,
                 TREATMENT = samples$TREATMENT,
                 Genotype = samples$genotype,
                 WEEK = samples$time)

smpl <- merge(t1,
              t2,
              by = "SAMPLE_NAME")

p1 <- ggplot(smpl,
             aes(x = SAMPLE_NAME,
                 y = Total,
                 fill = TREATMENT,
                 colour = WEEK)) +
  facet_wrap(~ Genotype,
             scale = "free_x") +
  geom_bar(stat = "identity") +
  scale_x_discrete("") +
  scale_y_continuous("Number of Reads") +
  scale_fill_discrete("Treatment") +
  theme(axis.text.x = element_text(angle = 45,
                                   hjust = 1)) 
ggplotly(p1)
tmp <- copy(smpl)
tmp$WEEK <- factor(tmp$WEEK,
                    levels = c("baseline",
                               "week1",
                               "week8"),
                    labels = c("Week 0",
                               "Week 1",
                               "Week 8"))
tmp$Genotype <- factor(tmp$Genotype,
                       levels = c("widetype",
                                  "nrf2KO"),
                       labels = c("Wild Type",
                                  "Nrf2 KO"))
p1 <- ggplot(tmp,
             aes(x = SAMPLE_NAME,
                 y = Total,
                 group = TREATMENT,
                 fill = TREATMENT)) +
  facet_wrap(~ Genotype + WEEK,
             scale = "free_x") +
  geom_bar(stat = "identity",
           color = "black") +
  scale_x_discrete("") +
  scale_y_continuous("Number of Reads") +
  scale_fill_grey("Treatment", 
                  start = 0.1, 
                  end = 1,
                  na.value = "red",
                  aesthetics = "fill") +
  theme_bw() + 
  theme(panel.border = element_blank(), 
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(), 
        axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        legend.position = "top")

tiff(filename = "tmp/seq_depth.tiff",
     height = 6,
     width = 6,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

print(p1)

8 Richness (Alpha diversity)

Shannon index (aka Shannon enthrophy) is calculated as:
H’ = -sum(1 to R)p(i)ln(p(i)) When there is exactly 1 type of data (e.g. a single species in the sample), H’=0. The opposite scenario is when there are R>1 species present in the sample in the exact same amounts and H’=ln(R).

Shannon’s diversity index was calculated for each sample and ploted over time using the 7,764 from the 13 Phylum above.

shannon.ndx <- estimate_richness(ps0,
                                 measures = "Shannon")

shannon.ndx <- data.table(SAMPLE_NAME = rownames(shannon.ndx),
                          shannon.ndx)

smpl <- merge(smpl,
              shannon.ndx,
              by = "SAMPLE_NAME")

p1 <- ggplot(smpl,
             aes(x = Total,
                 y = Shannon,
                 fill = Genotype,
                 shape = WEEK)) +
  geom_point(size = 2) +
  scale_shape_manual(breaks = unique(smpl$WEEK),
                     values = 21:23)

tiff(filename = "tmp/shannon_vs_depth.tiff",
     height = 5,
     width = 6,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

ggplotly(p1)

Even though estimate_richness function does not adjust for the sequencing depth, there is no correlation between the index and the sample’s sequecing depth. Proceed with the comparison.

9 Shannon idex over time

p1 <- plot_richness(ps0,
                    x = "time", 
                    measures = "Shannon") +
  facet_wrap(~ genotype) +
  geom_line(aes(group = ID),
            color = "black") +
  geom_point(aes(fill = TREATMENT),
             shape = 21,
             size = 3,
             color = "black") +
  scale_x_discrete("") +
  theme(axis.text.x = element_text(angle = 30,
                                   hjust = 1,
                                   vjust = 1))

ggplotly(p = p1,
         tooltip = c("ID",
                     "value"))

p1 <- p1 + 
  scale_fill_discrete("") +
  theme(legend.position = "top")

tiff(filename = "tmp/shannon.tiff",
     height = 4,
     width = 5,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

The plot above suggests that the largest differences in alpha diversity (as measured by Shannon’s index) are in genotype.

10 Average Shannon Index

# Average shannon index by treatment group
tmp <- copy(smpl)

tmp[, mu := mean(Shannon),
    by = list(TREATMENT,
              Genotype,
              WEEK)]
tmp[, sem := sd(Shannon)/sqrt(.N),
    by = list(TREATMENT,
                 Genotype,
                 WEEK)]
tmp <- unique(tmp[, c("TREATMENT",
                      "Genotype",
                      "WEEK",
                      "mu",
                      "sem")])
tmp$WEEK <- factor(tmp$WEEK,
                   levels = c("baseline",
                              "week1",
                              "week8"),
                   labels = c("Week 0",
                              "Week 1",
                              "Week 8"))
tmp$Genotype <- factor(tmp$Genotype,
                       levels = c("widetype",
                                  "nrf2KO"),
                       labels = c("Wild Type",
                                  "Nrf2 KO"))

p1 <- ggplot(tmp,
             aes(x = WEEK,
                 y = mu,
                 ymin = mu - sem,
                 ymax = mu + sem,
                 fill = TREATMENT,
                 group = TREATMENT)) +
  facet_wrap(~ Genotype) +
  geom_errorbar(position = position_dodge(0.4),
                width = 0.4) +
  geom_line(position = position_dodge(0.4)) +
  geom_point(size = 3,
             shape = 21,
             position = position_dodge(0.4)) +
  scale_x_discrete("") +
  scale_y_continuous("Shannon Index") +
  theme(axis.text.x = element_text(angle = 45,
                                   hjust = 1),
        legend.position = "top") 

tiff(filename = "tmp/avg_shannon.tiff",
     height = 5,
     width = 6,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

print(p1)

Test if the richness changed between the baseline and Week 8.

smpl$TREATMENT <- factor(smpl$TREATMENT,
                         levels = c("DSS",
                                    "Naive",
                                    "DSS+PEITC",
                                    "DSS+Cranberry"))
tmp <- droplevels(smpl[WEEK != "week1"])
m1 <- lm(Shannon  ~ WEEK*(TREATMENT + Genotype),
         # offset = Total,
         data = tmp)
summary(m1)

Call:
lm(formula = Shannon ~ WEEK * (TREATMENT + Genotype), data = tmp)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.316186 -0.091027  0.007886  0.110704  0.293230 

Coefficients:
                                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)                       5.94987    0.07064  84.233  < 2e-16 ***
WEEKweek8                         0.01158    0.09989   0.116   0.9084    
TREATMENTNaive                    0.14581    0.08935   1.632   0.1109    
TREATMENTDSS+PEITC               -0.03923    0.08935  -0.439   0.6631    
TREATMENTDSS+Cranberry           -0.22582    0.08935  -2.527   0.0158 *  
Genotypewidetype                 -0.54156    0.06318  -8.572 2.06e-10 ***
WEEKweek8:TREATMENTNaive          0.01181    0.12636   0.093   0.9261    
WEEKweek8:TREATMENTDSS+PEITC      0.01652    0.12636   0.131   0.8966    
WEEKweek8:TREATMENTDSS+Cranberry  0.21535    0.12636   1.704   0.0965 .  
WEEKweek8:Genotypewidetype        0.23085    0.08935   2.584   0.0137 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1548 on 38 degrees of freedom
Multiple R-squared:  0.7845,    Adjusted R-squared:  0.7335 
F-statistic: 15.37 on 9 and 38 DF,  p-value: 3.671e-10
m2 <- lmer(Shannon  ~ WEEK*(TREATMENT + Genotype) + (1 | ID),
           # offset = Total,
           data = tmp)
summary(m2)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: Shannon ~ WEEK * (TREATMENT + Genotype) + (1 | ID)
   Data: tmp

REML criterion at convergence: -22.2

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-1.53721 -0.47495  0.06753  0.44489  1.53874 

Random effects:
 Groups   Name        Variance Std.Dev.
 ID       (Intercept) 0.01259  0.1122  
 Residual             0.01136  0.1066  
Number of obs: 48, groups:  ID, 24

Fixed effects:
                                 Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)                       5.94987    0.07064 29.76837  84.233  < 2e-16 ***
WEEKweek8                         0.01158    0.06879 19.00000   0.168  0.86814    
TREATMENTNaive                    0.14581    0.08935 29.76837   1.632  0.11322    
TREATMENTDSS+PEITC               -0.03923    0.08935 29.76837  -0.439  0.66379    
TREATMENTDSS+Cranberry           -0.22582    0.08935 29.76837  -2.527  0.01704 *  
Genotypewidetype                 -0.54156    0.06318 29.76837  -8.572 1.55e-09 ***
WEEKweek8:TREATMENTNaive          0.01181    0.08701 19.00000   0.136  0.89350    
WEEKweek8:TREATMENTDSS+PEITC      0.01652    0.08701 19.00000   0.190  0.85139    
WEEKweek8:TREATMENTDSS+Cranberry  0.21535    0.08701 19.00000   2.475  0.02291 *  
WEEKweek8:Genotypewidetype        0.23085    0.06152 19.00000   3.752  0.00135 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
                     (Intr) WEEKw8 TREATMENTN TREATMENTDSS+P TREATMENTDSS+C Gntypw
WEEKweek8            -0.487                                                       
TREATMENTNv          -0.632  0.308                                                
TREATMENTDSS+P       -0.632  0.308  0.500                                         
TREATMENTDSS+C       -0.632  0.308  0.500      0.500                              
Gentypwdtyp          -0.447  0.218  0.000      0.000          0.000               
WEEK8:TREATMENTN      0.308 -0.632 -0.487     -0.243         -0.243          0.000
WEEK8:TREATMENTDSS+P  0.308 -0.632 -0.243     -0.487         -0.243          0.000
WEEK8:TREATMENTDSS+C  0.308 -0.632 -0.243     -0.243         -0.487          0.000
WEEKwk8:Gnt           0.218 -0.447  0.000      0.000          0.000         -0.487
                     WEEK8:TREATMENTN WEEK8:TREATMENTDSS+P WEEK8:TREATMENTDSS+C
WEEKweek8                                                                      
TREATMENTNv                                                                    
TREATMENTDSS+P                                                                 
TREATMENTDSS+C                                                                 
Gentypwdtyp                                                                    
WEEK8:TREATMENTN                                                               
WEEK8:TREATMENTDSS+P  0.500                                                    
WEEK8:TREATMENTDSS+C  0.500            0.500                                   
WEEKwk8:Gnt           0.000            0.000                0.000              

11 Calculate change in Shannon index from baseline

dd <- smpl
dd[, delta := Shannon - Shannon[WEEK == "baseline"],
   by = ID]
dd$diff <- paste(dd$WEEK,
                 "-baseline",
                 sep = "")
dd <- dd[WEEK != "baseline",]
p1 <- ggplot(dd,
             aes(x = TREATMENT,
                 y = delta,
                 fill = Genotype)) +
  facet_wrap(~ diff) +
  geom_hline(yintercept = 0,
             linetype = "dashed") +
  geom_point(position = position_dodge(0.3),
             shape = 21,
             size = 3) +
  scale_y_continuous("Shannon Index Percent Change from Baseline") +
  theme(axis.text.x = element_text(angle = 45,
                                   hjust = 1))
print(p1)

dd$TREATMENT <- factor(dd$TREATMENT,
                        levels = c("DSS",
                                   "Naive",
                                   "DSS+PEITC",
                                   "DSS+Cranberry"))
dd$Genotype <- factor(dd$Genotype,
                       levels = c("widetype",
                                  "nrf2KO"))
m1 <- lm(delta ~ TREATMENT*Genotype,
         data = dd)
summary(m1)

Call:
lm(formula = delta ~ TREATMENT * Genotype, data = dd)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.40513 -0.09560 -0.02012  0.09568  0.35517 

Coefficients:
                                      Estimate Std. Error t value Pr(>|t|)   
(Intercept)                            0.25142    0.07286   3.451  0.00133 **
TREATMENTNaive                        -0.04426    0.10303  -0.430  0.66985   
TREATMENTDSS+PEITC                    -0.15777    0.10303  -1.531  0.13358   
TREATMENTDSS+Cranberry                 0.04463    0.10303   0.433  0.66720   
Genotypenrf2KO                        -0.18412    0.10303  -1.787  0.08153 . 
TREATMENTNaive:Genotypenrf2KO         -0.02851    0.14571  -0.196  0.84586   
TREATMENTDSS+PEITC:Genotypenrf2KO      0.24747    0.14571   1.698  0.09721 . 
TREATMENTDSS+Cranberry:Genotypenrf2KO  0.07927    0.14571   0.544  0.58946   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1785 on 40 degrees of freedom
Multiple R-squared:  0.249, Adjusted R-squared:  0.1176 
F-statistic: 1.894 on 7 and 40 DF,  p-value: 0.09608
# No significant interactions, proceed with 2-way analysis
m2 <- lm(delta ~ TREATMENT + Genotype,
         data = dd)
summary(m2)

Call:
lm(formula = delta ~ TREATMENT + Genotype, data = dd)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.49158 -0.09742 -0.01290  0.11101  0.35281 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)    
(Intercept)             0.21414    0.05849   3.661 0.000683 ***
TREATMENTNaive         -0.05851    0.07399  -0.791 0.433377    
TREATMENTDSS+PEITC     -0.03404    0.07399  -0.460 0.647813    
TREATMENTDSS+Cranberry  0.08427    0.07399   1.139 0.261014    
Genotypenrf2KO         -0.10956    0.05232  -2.094 0.042176 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1812 on 43 degrees of freedom
Multiple R-squared:  0.1674,    Adjusted R-squared:  0.08999 
F-statistic: 2.162 on 4 and 43 DF,  p-value: 0.08947

At Week 8 there was significantly smaller increase of alpha diversity from baseline in Nrf2 KO compared to WT, and in DSS+Cranberry compared to DSS only.

12 Load aminoacids

aa <- fread("data_sep2019/sep2019_aminoacids.csv")
aa <- aa[!is.na(ID), ]
aa$ID <- paste0(aa$ID,
                aa$CAGE)
smpl1 <- unique(smpl[, c("ID",
                            "TREATMENT",
                            "Genotype")])
smpl1$ID <- as.character(smpl1$ID)
aa <- merge(smpl1,
            aa,
            by = "ID")
aa[, trt_week := paste(TREATMENT,
                       WEEK,
                       sep = "_")]
aa$trt_week <- factor(aa$trt_week,
                      levels = c("Naive_week2",
                                 "Naive_week6",
                                 "DSS_week2",
                                 "DSS_week6",
                                 "DSS+Cranberry_week2",
                                 "DSS+Cranberry_week6" ,
                                 "DSS+PEITC_week2",
                                 "DSS+PEITC_week6"))

13 Aminoacids by animal, treatment group and timepoint

for (i in 8:(ncol(aa) - 1)) {
  tmp <- aa[, c(1, 3, 7, ncol(aa), i), with = FALSE]
  colnames(tmp)[5] <- "Y"
  p1 <- ggplot(tmp,
               aes(x = trt_week,
                   y = Y,
                   fill = Genotype,
                   group = ID)) +
    geom_line(position = position_dodge(0.3)) +
    geom_point(shape = 21,
               size = 3,
               position = position_dodge(0.3)) +
    scale_x_discrete("") +
    scale_y_continuous(colnames(aa)[i]) +
    theme(axis.text.x = element_text(angle = 45,
                                     hjust = 1))
  # tiff(filename = paste0("tmp/",
  #                        colnames(aa)[i],
  #                        ".tiff"),
  #      height = 4,
  #      width = 5,
  #      units = "in",
  #      res = 600,
  #      compression = "lzw+p")
  # print(p1)
  # graphics.off()
  
  print(p1)
}

14 Aminoacids over time, group averages

out <- list()
for (i in 8:27) {
  tmp <- aa[, c(2, 3, 7, i), 
            with = FALSE]
  names(tmp)[4] <- "val"
  
  tmp[, mu := mean(val,
                   na.rm = TRUE),
      by = list(TREATMENT,
                Genotype,
                WEEK)]
  tmp[, sem := sd(val,
                  na.rm = TRUE)/sqrt(.N),
      by = list(TREATMENT,
                Genotype,
                WEEK)]
  out[[i - 7]] <- data.table(Aminoacid = names(aa)[i],
                             unique(tmp[, c("TREATMENT",
                                            "Genotype",
                                            "WEEK",
                                            "mu",
                                            "sem")]))
}
muaa <- rbindlist(out)
muaa$Aminoacid <- factor(muaa$Aminoacid,
                         levels = unique(muaa$Aminoacid))
muaa$Genotype <- factor(muaa$Genotype,
                        levels = c("widetype",
                                   "nrf2KO"),
                        labels = c("Wild Type",
                                   "Nrf2 KO"))
for (i in 1:nlevels(muaa$Aminoacid)) {
  p1 <- ggplot(muaa[Aminoacid == levels(muaa$Aminoacid)[i], ],
               aes(x = WEEK,
                   y = mu,
                   ymin = mu - sem,
                   ymax = mu + sem,
                   fill = TREATMENT,
                   group = TREATMENT)) +
    facet_wrap(~ Genotype) +
    geom_errorbar(position = position_dodge(0.4),
                  width = 0.4) +
    geom_line(position = position_dodge(0.4)) +
    geom_point(size = 3,
               shape = 21,
               position = position_dodge(0.4)) +
    scale_x_discrete("",
                     breaks = c("week2",
                                "week6"),
                     labels = c("Week 2",
                                "Week 6")) +
    scale_y_continuous(levels(muaa$Aminoacid)[i]) +
    theme(axis.text.x = element_text(angle = 45,
                                     hjust = 1),
          legend.position = "top") 
  
  # tiff(filename = paste0("tmp/avg_",
  #                        levels(muaa$Aminoacid)[i],
  #                        ".tiff"),
  #      height = 5,
  #      width = 6,
  #      units = "in",
  #      res = 600,
  #      compression = "lzw+p")
  # print(p1)
  # graphics.off()
  
  print(p1)
}

15 Aminoacid data PCA

dt_pca <- aa[, Alanine:glutamine]
# m1 <- prcomp(dt_pca,
#              center = TRUE,
#              scale. = TRUE)
# m1 <- prcomp(dt_pca,
#              center = FALSE,
#              scale. = FALSE)
m1 <- prcomp(dt_pca)
summary(m1)
Importance of components:
                          PC1    PC2     PC3     PC4     PC5     PC6     PC7     PC8
Standard deviation     4.8108 2.5833 1.78182 1.13495 0.93367 0.84949 0.62035 0.49052
Proportion of Variance 0.6276 0.1810 0.08609 0.03493 0.02364 0.01957 0.01044 0.00652
Cumulative Proportion  0.6276 0.8086 0.89466 0.92959 0.95323 0.97280 0.98323 0.98976
                           PC9    PC10    PC11    PC12   PC13    PC14    PC15    PC16
Standard deviation     0.35960 0.26786 0.22940 0.20322 0.1486 0.13250 0.11932 0.11154
Proportion of Variance 0.00351 0.00195 0.00143 0.00112 0.0006 0.00048 0.00039 0.00034
Cumulative Proportion  0.99326 0.99521 0.99663 0.99775 0.9983 0.99883 0.99922 0.99955
                          PC17    PC18    PC19    PC20
Standard deviation     0.08896 0.07274 0.05110 0.02565
Proportion of Variance 0.00021 0.00014 0.00007 0.00002
Cumulative Proportion  0.99977 0.99991 0.99998 1.00000
# Select PC-s to pliot (PC1 & PC2)
choices <- 1:2
# Scores, i.e. points (df.u)
dt.scr <- data.table(m1$x[, choices])
# Add grouping variable
dt.scr$grp <- aa$trt_week
dt.scr$TREATMENT <- aa$TREATMENT
dt.scr$WEEK <- aa$WEEK
dt.scr
# Loadings, i.e. arrows (df.v)
dt.rot <- as.data.frame(m1$rotation[, choices])
dt.rot$feat <- rownames(dt.rot)
dt.rot <- data.table(dt.rot)
dt.rot
dt.load <- melt.data.table(dt.rot,
                           id.vars = "feat",
                           measure.vars = 1:2,
                           variable.name = "pc",
                           value.name = "loading")
dt.load$feat <- factor(dt.load$feat,
                       levels = unique(dt.load$feat))
# Plot loadings
p0 <- ggplot(data = dt.load,
             aes(x = feat,
                 y = loading)) +
  facet_wrap(~ pc,
             nrow = 2) +
  geom_bar(stat = "identity") +
  ggtitle("PC Loadings") +
  theme(plot.title = element_text(hjust = 0.5),
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))
tiff(filename = "tmp/pc.1.2_loadings.tiff",
     height = 5,
     width = 8,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

# Axis labels
u.axis.labs <- paste(colnames(dt.rot)[1:2], 
                     sprintf('(%0.1f%% explained var.)', 
                             100*m1$sdev[choices]^2/sum(m1$sdev^2)))
u.axis.labs
[1] "PC1 (62.8% explained var.)" "PC2 (18.1% explained var.)"
# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = grp),
             shape = 21,
             size = 2,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 10*PC1,
                   yend = 10*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               # size = 1, 
               color = "black") +
  geom_text(aes(x = 11*PC1,
                y = 11*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_discrete(name = "Group") +
  ggtitle("Biplot of Aminoacids") +
  theme(plot.title = element_text(hjust = 0.5,
                                  size = 20))
tiff(filename = "tmp/aminoacids_biplot.tiff",
     height = 10,
     width = 10,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
p2 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = WEEK),
             shape = 21,
             size = 2,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 10*PC1,
                   yend = 10*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               size = 1.2, 
               color = "black") +
  geom_text(aes(x = 11*PC1,
                y = 11*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_discrete(name = "Week") +
  ggtitle("Biplot of Aminoacids") +
  theme(plot.title = element_text(hjust = 0.5,
                                  size = 20))
tiff(filename = "tmp/aminoacids_by_week_biplot.tiff",
     height = 10,
     width = 10,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p2)
graphics.off()
ggplotly(p2)
p2 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = TREATMENT),
             shape = 21,
             size = 2,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 10*PC1,
                   yend = 10*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               size = 1.2, 
               color = "black") +
  geom_text(aes(x = 11*PC1,
                y = 11*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_discrete(name = "Treatment") +
  ggtitle("Biplot of Aminoacids") +
  theme(plot.title = element_text(hjust = 0.5,
                                  size = 20))
tiff(filename = "tmp/aminoacids_by_trt_biplot.tiff",
     height = 10,
     width = 10,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p2)
graphics.off()
ggplotly(p2)

16 Remove unmapped OTUs

The 311 unmapped OTUs were removed from further analysis (with 7,247 OTUs left).

ps1 <- subset_taxa(ps0, 
                   !is.na(Phylum))
dim(ps1@otu_table@.Data)
[1]   72 7247

17 Counts at Phylum level

18 Relative abundance (%) at Phylum level

Remove phyla with relative abundance of >= 1% in less than 10% of samples.

t1 <- data.table(Phylum = ra_p$Phylum,
                 `Number of Samples` = rowSums(ra_p[, 2:ncol(ra_p)] >= 0.01))
t1$`Percent Samples` <-  t1$`Number of Samples`/72
setorder(t1, -`Number of Samples`)
datatable(t1,
          rownames = FALSE,
          caption = "Taxonomic  count table",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t1))) %>%
  formatPercentage(columns = 3,
                   digits = 1)

We will remove Chlamydiae from this analysis.

[1] "Firmicutes, Bacteroidetes, Proteobacteria, Verrucomicrobia, Epsilonbacteraeota, Actinobacteria, Deferribacteres, Patescibacteria, Cyanobacteria"

7,224 OTUs, down from 7,247 OTUs in the previous table.

19 Relative Abundance in Samples at Different Taxonomic Ranks

19.1 1. Class

20 PCA at Class level

dt_pca <- t(ra_c[, 3:ncol(ra_c)])
colnames(dt_pca) <- ra_c$Class
dt_pca_c <- data.table(SAMPLE_NAME = rownames(dt_pca),
                       dt_pca)
dt_pca_c <- merge(smpl,
                  dt_pca_c,
                  by = "SAMPLE_NAME")
# m1 <- prcomp(dt_pca,
#              center = TRUE,
#              scale. = TRUE)
# m1 <- prcomp(dt_pca,
#              center = FALSE,
#              scale. = FALSE)
m1 <- prcomp(dt_pca)
summary(m1)
Importance of components:
                           PC1    PC2    PC3     PC4     PC5     PC6     PC7     PC8
Standard deviation     14.6908 8.5044 7.5927 5.76824 3.41220 2.73038 2.43631 1.46850
Proportion of Variance  0.5294 0.1774 0.1414 0.08162 0.02856 0.01829 0.01456 0.00529
Cumulative Proportion   0.5294 0.7068 0.8482 0.92987 0.95844 0.97672 0.99128 0.99657
                           PC9    PC10    PC11    PC12    PC13      PC14
Standard deviation     0.93207 0.55762 0.43780 0.15826 0.02399 8.187e-17
Proportion of Variance 0.00213 0.00076 0.00047 0.00006 0.00000 0.000e+00
Cumulative Proportion  0.99870 0.99947 0.99994 1.00000 1.00000 1.000e+00
# Select PC-s to pliot (PC1 & PC2)
choices <- 1:2
# Scores, i.e. points (df.u)
dt.scr <- data.table(m1$x[, choices])
# Add grouping variable
dt.scr$grp <- paste(dt_pca_c$TREATMENT,
                    dt_pca_c$WEEK,
                    dt_pca_c$Genotype)
dt.scr$TREATMENT <- dt_pca_c$TREATMENT
dt.scr$WEEK <- dt_pca_c$WEEK
dt.scr$Genotype <- dt_pca_c$Genotype
dt.scr
# Loadings, i.e. arrows (df.v)
dt.rot <- as.data.frame(m1$rotation[, choices])
dt.rot$feat <- rownames(dt.rot)
dt.rot <- data.table(dt.rot)
dt.rot
dt.load <- melt.data.table(dt.rot,
                           id.vars = "feat",
                           measure.vars = 1:2,
                           variable.name = "pc",
                           value.name = "loading")
dt.load$feat <- factor(dt.load$feat,
                       levels = unique(dt.load$feat))
# Plot loadings
p0 <- ggplot(data = dt.load,
             aes(x = feat,
                 y = loading)) +
  facet_wrap(~ pc,
             nrow = 2) +
  geom_bar(stat = "identity") +
  ggtitle("PC Loadings") +
  theme(plot.title = element_text(hjust = 0.5),
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))
tiff(filename = "tmp/pc.1.2_loadings_class.tiff",
     height = 5,
     width = 8,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

# Axis labels
u.axis.labs <- paste(colnames(dt.rot)[1:2], 
                     sprintf('(%0.1f%% explained var.)', 
                             100*m1$sdev[choices]^2/sum(m1$sdev^2)))
u.axis.labs
[1] "PC1 (52.9% explained var.)" "PC2 (17.7% explained var.)"
# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = grp),
             shape = 21,
             size = 2,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 40*PC1,
                   yend = 40*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               # size = 1, 
               color = "black") +
  geom_text(aes(x = 44*PC1,
                y = 44*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_discrete(name = "Group") +
  ggtitle("Biplot of Classes of Bacteria") +
  theme(plot.title = element_text(hjust = 0.5,
                                  size = 20)) 
tiff(filename = "tmp/class_biplot_grp.tiff",
     height = 10,
     width = 10,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
# Find centers of each group
grpg <- "grp"
var1 <- eval(parse(text = paste("dt.scr$",
                                grpg,
                                sep = "")))
cntr <- data.table(Group = unique(var1),
                   PC1 = aggregate(x = dt.scr$PC1,
                                   by = list(var1),
                                   FUN = "mean")$x,
                   PC2 = aggregate(x = dt.scr$PC2,
                                   by = list(var1),
                                   FUN = "mean")$x)
p2 <- p1 + geom_label(data = cntr,
                      aes(x = PC1,
                          y = PC2,
                          label = Group,
                          colour = Group),
                      alpha = 0.5,
                      size = 3) +
  scale_color_discrete(guide = FALSE) +
  theme(legend.position = "none")
print(p2)

# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = Genotype),
             shape = 21,
             size = 2,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 40*PC1,
                   yend = 40*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               # size = 1, 
               color = "black") +
  geom_text(aes(x = 44*PC1,
                y = 44*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_discrete(name = "Group") +
  ggtitle("Biplot of Classes of Bacteria") +
  theme(plot.title = element_text(hjust = 0.5,
                                  size = 20))
tiff(filename = "tmp/class_biplot_genotype.tiff",
     height = 10,
     width = 10,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
# Find centers of each group
grpg <- "Genotype"
var1 <- eval(parse(text = paste("dt.scr$",
                                grpg,
                                sep = "")))
cntr <- data.table(Group = unique(var1),
                   PC1 = aggregate(x = dt.scr$PC1,
                                   by = list(var1),
                                   FUN = "mean")$x,
                   PC2 = aggregate(x = dt.scr$PC2,
                                   by = list(var1),
                                   FUN = "mean")$x)
p2 <- p1 + geom_label(data = cntr,
                      aes(x = PC1,
                          y = PC2,
                          label = Group,
                          colour = Group),
                      alpha = 0.5,
                      size = 3) +
  scale_color_discrete(guide = FALSE) +
  theme(legend.position = "none")
print(p2)

# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = WEEK),
             shape = 21,
             size = 2,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 40*PC1,
                   yend = 40*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               # size = 1, 
               color = "black") +
  geom_text(aes(x = 44*PC1,
                y = 44*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_discrete(name = "Group") +
  ggtitle("Biplot of Classes of Bacteria") +
  theme(plot.title = element_text(hjust = 0.5,
                                  size = 20))
tiff(filename = "tmp/class_biplot_week.tiff",
     height = 10,
     width = 10,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
# Find centers of each group
grpg <- "WEEK"
var1 <- eval(parse(text = paste("dt.scr$",
                                grpg,
                                sep = "")))
cntr <- data.table(Group = unique(var1),
                   PC1 = aggregate(x = dt.scr$PC1,
                                   by = list(var1),
                                   FUN = "mean")$x,
                   PC2 = aggregate(x = dt.scr$PC2,
                                   by = list(var1),
                                   FUN = "mean")$x)
p2 <- p1 + geom_label(data = cntr,
                      aes(x = PC1,
                          y = PC2,
                          label = Group,
                          colour = Group),
                      alpha = 0.5,
                      size = 3) +
  scale_color_discrete(guide = FALSE) +
  theme(legend.position = "none")
print(p2)

# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = TREATMENT),
             shape = 21,
             size = 3,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 40*PC1,
                   yend = 40*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               # size = 1, 
               color = "black") +
  geom_text(aes(x = 44*PC1,
                y = 44*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_manual(name = "Treatment",
                    breaks = levels(dt.scr$TREATMENT),
                                    values = c("red",
                                               "green",
                                               "orange",
                                               "blue")) +
                      ggtitle("Biplot of Classes of Bacteria") +
                      theme(plot.title = element_text(hjust = 0.5,
                                                      size = 20))
                    ggplotly(p1)
# Find centers of each group
# grpg <- "TREATMENT"
# var1 <- eval(parse(text = paste("dt.scr$",
#                                 grpg,
#                                 sep = "")))
# cntr <- data.table(Group = levels(var1),
#                    PC1 = aggregate(x = dt.scr$PC1,
#                                    by = list(var1),
#                                    FUN = "mean")$x,
#                    PC2 = aggregate(x = dt.scr$PC2,
#                                    by = list(var1),
#                                    FUN = "mean")$x)
cntr <- data.table(PC1 = aggregate(x = dt.scr$PC1,
                                   by = list(dt.scr$TREATMENT),
                                   FUN = "mean"),
                   PC2 = aggregate(x = dt.scr$PC2,
                                   by = list(var1),
                                   FUN = "mean")$x)
colnames(cntr) <- c("TREATMENT",
                    "PC1",
                    "PC2")
p2 <- p1 + geom_label(data = cntr,
                      aes(x = PC1,
                          y = PC2,
                          label = TREATMENT,
                          colour = TREATMENT),
                      alpha = 0.5,
                      size = 3) +
  scale_color_manual(guide = FALSE,
                    breaks = levels(cntr$TREATMENT),
                                    values = c("red",
                                               "green",
                                               "orange",
                                               "blue")) +
  theme(legend.position = "none")
tiff(filename = "tmp/class_biplot_trt.tiff",
     height = 8,
     width = 8,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p2)
graphics.off()
print(p2)

# Covariates only
m1 <- multinom(TREATMENT ~ WEEK + Genotype,
               data = dt.scr)
# weights:  20 (12 variable)
initial  value 99.813194 
final  value 99.813194 
converged
summary(m1)
Call:
multinom(formula = TREATMENT ~ WEEK + Genotype, data = dt.scr)

Coefficients:
              (Intercept) WEEKweek1 WEEKweek8 Genotypewidetype
Naive                   0         0         0                0
DSS+PEITC               0         0         0                0
DSS+Cranberry           0         0         0                0

Std. Errors:
              (Intercept) WEEKweek1 WEEKweek8 Genotypewidetype
Naive           0.6666667 0.8164966 0.8164966        0.6666667
DSS+PEITC       0.6666667 0.8164966 0.8164966        0.6666667
DSS+Cranberry   0.6666667 0.8164966 0.8164966        0.6666667

Residual Deviance: 199.6264 
AIC: 223.6264 
prd1 <- predict(m1)
t1 <- table(Predicted = prd1,
            Observed = dt.scr$TREATMENT)
# PC1 alone
m2 <- multinom(TREATMENT ~ PC1,
               data = dt.scr)
# weights:  12 (6 variable)
initial  value 99.813194 
iter  10 value 84.652280
final  value 84.650617 
converged
summary(m2)
Call:
multinom(formula = TREATMENT ~ PC1, data = dt.scr)

Coefficients:
              (Intercept)         PC1
Naive         -0.84291965 -0.13135533
DSS+PEITC      0.02563488 -0.01778110
DSS+Cranberry -0.28377674  0.04267039

Std. Errors:
              (Intercept)        PC1
Naive           0.5329226 0.03966130
DSS+PEITC       0.3375675 0.02567473
DSS+Cranberry   0.3902129 0.02668075

Residual Deviance: 169.3012 
AIC: 181.3012 
prd2 <- predict(m2)
t2 <- table(Predicted = prd2,
            Observed = dt.scr$TREATMENT)
# PC1 with covariates
m3 <- multinom(TREATMENT ~ PC1 + WEEK + Genotype,
               data = dt.scr)
# weights:  24 (15 variable)
initial  value 99.813194 
iter  10 value 78.199054
final  value 77.966110 
converged
summary(m3)
Call:
multinom(formula = TREATMENT ~ PC1 + WEEK + Genotype, data = dt.scr)

Coefficients:
              (Intercept)         PC1   WEEKweek1  WEEKweek8 Genotypewidetype
Naive         -1.69181404 -0.16561286 -0.19417414 -0.2467395        2.0439498
DSS+PEITC     -0.22775882 -0.03756158 -0.03426154 -0.1624952        0.6998366
DSS+Cranberry  0.04994931  0.11984007  0.18496264  0.6354061       -2.2783047

Std. Errors:
              (Intercept)        PC1 WEEKweek1 WEEKweek8 Genotypewidetype
Naive           0.9208565 0.04798080 1.0184358 0.9866132        1.0821427
DSS+PEITC       0.7006164 0.03813898 0.8248932 0.8419015        0.9838589
DSS+Cranberry   0.7578087 0.04894181 0.8842508 0.9154535        1.1724461

Residual Deviance: 155.9322 
AIC: 185.9322 
prd3 <- predict(m3)
t3 <- table(Predicted = prd3,
            Observed = dt.scr$TREATMENT)
# PC1 + PC2 with covariates
m4 <- multinom(TREATMENT ~ PC1 + PC2 + WEEK + Genotype,
               data = dt.scr)
# weights:  28 (18 variable)
initial  value 99.813194 
iter  10 value 77.643401
iter  20 value 76.157664
final  value 76.157652 
converged
summary(m4)
Call:
multinom(formula = TREATMENT ~ PC1 + PC2 + WEEK + Genotype, data = dt.scr)

Coefficients:
              (Intercept)         PC1         PC2  WEEKweek1   WEEKweek8 Genotypewidetype
Naive          -1.6723699 -0.16055402  0.02692425  0.0603261 -0.04440483        1.7116558
DSS+PEITC      -0.1610640 -0.03200954 -0.04731926 -0.3059877 -0.35846181        0.6645649
DSS+Cranberry  -0.1487237  0.11347301  0.04018812  0.3641810  0.72081476       -2.0106669

Std. Errors:
              (Intercept)        PC1        PC2 WEEKweek1 WEEKweek8 Genotypewidetype
Naive           0.9329651 0.04827333 0.04795722 1.1064244 1.0330649         1.083235
DSS+PEITC       0.7176961 0.03961699 0.04860606 0.8745219 0.8762840         1.022935
DSS+Cranberry   0.8377326 0.04936837 0.06510574 0.9608816 0.9434467         1.204373

Residual Deviance: 152.3153 
AIC: 188.3153 
prd4 <- predict(m4)
t4 <- table(Predicted = prd4,
            Observed = dt.scr$TREATMENT)
# Confusion tables
datatable(cbind(t1), 
          caption = "Covariates Only")

datatable(cbind(t2),
          caption = "PC1 Only")

datatable(cbind(t3),
          caption = "PC1 with covariates")

datatable(cbind(t4),
          caption = "PC1 + PC2 with covariates")

# Compare models
anova(m1, m3)
Likelihood ratio tests of Multinomial Models

Response: TREATMENT
                  Model Resid. df Resid. Dev   Test    Df LR stat.      Pr(Chi)
1       WEEK + Genotype       204   199.6264                                   
2 PC1 + WEEK + Genotype       201   155.9322 1 vs 2     3 43.69417 1.752679e-09
anova(m2, m3)
Likelihood ratio tests of Multinomial Models

Response: TREATMENT
                  Model Resid. df Resid. Dev   Test    Df LR stat.   Pr(Chi)
1                   PC1       210   169.3012                                
2 PC1 + WEEK + Genotype       201   155.9322 1 vs 2     9 13.36901 0.1466072
anova(m4, m3)
Likelihood ratio tests of Multinomial Models

Response: TREATMENT
                        Model Resid. df Resid. Dev   Test    Df LR stat.  Pr(Chi)
1       PC1 + WEEK + Genotype       201   155.9322                               
2 PC1 + PC2 + WEEK + Genotype       198   152.3153 1 vs 2     3 3.616917 0.305912

The results suggest that:
a. Covariates alone (timepoint and genotype) cannot explain the difference between treatments.
b. Principal Component 1 (PC1) can explain the differences in relative abundance of classes in the samples. The model does not improve significantly by adding the covariates or the PC2. However, the covariates should stay in the model for adjustment, and PC2 slightly improves the predictions.
c. The full model (PC1 + PC2 + Week + Genotype) correctly classifies 12 out of 18 Naive samples, and 12 out of 18 DSS+Cranburry samples.

Continuing the same analysis at Order, Family and Genus levels.

DO ROC AUC NEST!!!

# # Output probobilities----
# prd1.1 <- predict(m1,
#                   type = "probs")
# prd1.1 <- data.table(ID = df.u$ID,
#                      Treatment = df.u$Treatment,
#                      round(prd1.1,
#                            4))
# 
# prd2.1 <- predict(m2,
#                   type = "probs")
# prd2.1 <- data.table(ID = df.u$ID,
#                      Treatment = df.u$Treatment,
#                      round(prd2.1,
#                            4))
# 
# # Sensitivity/Specificity
# # Tresholds
# trhd <- seq(0, 1, by = 0.01)
# 
# out1 <- list()
# for (i in 1:length(trhd)) {
#   tmp <- apply(prd1.1[, -c(1:2)],
#                MARGIN = 2,
#                FUN = function(a) {
#                  return(a >= trhd[i])
#                })
#   tmp2 <- apply(X = tmp,
#                 MARGIN = 2,
#                 FUN = function(a) {
#                   aggregate(x = a,
#                             by = list(prd1.1$Treatment),
#                             FUN = sum)$x
#                 })
#   tmp2
#   out1[[i]] <- c(sens = sum(diag(tmp2))/nrow(prd1.1),
#                  spec = (sum(tmp2[upper.tri(tmp2)]) + 
#                            sum(tmp2[lower.tri(tmp2)]))/(nrow(tmp)*(ncol(tmp) - 1)))
# }
# out1 <- data.table(do.call("rbind", out1))
# out1 <- unique(out1)
# 
# out2 <- list()
# for (i in 1:length(trhd)) {
#   tmp <- apply(prd2.1[, -c(1:2)],
#                MARGIN = 2,
#                FUN = function(a) {
#                  return(a >= trhd[i])
#                })
#   tmp2 <- apply(X = tmp,
#                 MARGIN = 2,
#                 FUN = function(a) {
#                   aggregate(x = a,
#                             by = list(prd2.1$Treatment),
#                             FUN = sum)$x
#                 })
#   out2[[i]] <- c(sens = sum(diag(tmp2))/nrow(prd2.1),
#                  spec = (sum(tmp2[upper.tri(tmp2)]) + 
#                            sum(tmp2[lower.tri(tmp2)]))/(nrow(tmp)*(ncol(tmp) - 1)))
# }
# out2 <- data.table(do.call("rbind", out2))
# out2 <- unique(out2)
# 
# # ROC
# roc1 <- auc(x = out1$spec,
#             y = out1$sens,
#             from = 0,
#             to = 1)
# 
# roc2 <- auc(x = out2$spec,
#             y = out2$sens,
#             from = 0,
#             to = 1)
# 
# # ROC plot
# plot(out1$sens ~ out1$spec,
#      type = "l",
#      xlim = c(0, 1),
#      ylim = c(0, 1),
#      xlab = "1 - Specificity",
#      ylab = "Sensitivity",
#      col = "blue")
# lines(out2$sens ~ out2$spec,
#       col = "red")
# text(x = c(0.8, 0.8),
#      y = c(0.2, 0.3),
#      label = c(paste("ROC(PC1) = ",
#                      round(roc1, 
#                            3)),
#                paste("\nROC(PC1+PC2) = ",
#                      round(roc2,
#                            3))),
#      col = c("blue",
#              "red"))
# abline(0, 1, lty = 2)
mu$Trt_Genotype <- factor(paste(mu$Treatment,
                          mu$Genotype,
                          sep = "_"))
p0 <- ggplot(mu,
             aes(x = Week,
                 y = x,
                 group = Trt_Genotype)) +
  facet_wrap(~ Class,
             scale = "free_y") +
  geom_line(position = position_dodge(0.3)) +
  geom_point(aes(fill = Trt_Genotype),
             shape = 21,
             size = 2,
             alpha = 0.5,
             position = position_dodge(0.3)) +
  scale_x_discrete("") +
  scale_y_continuous("Relative Abundance (%)") +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))
tiff(filename = "tmp/wt_class_over_time.tiff",
     height = 5,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

p1 <- ggplot(mu,
             aes(x = x,
                 y = Class,
                 color = Trt_Genotype,
                 shape = Week)) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)") 
tiff(filename = "tmp/wt_class_ra.tiff",
     height = 4,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1+
  theme(legend.position = "none"))

20.1 2. Order

mu$Trt_Genotype <- factor(paste(mu$Treatment,
                                mu$Genotype,
                                sep = "_"))

p0 <- ggplot(mu,
             aes(x = Week,
                 y = x,
                 group = Trt_Genotype)) +
  facet_wrap(~ Order,
             scale = "free_y") +
  geom_line(position = position_dodge(0.3)) +
  geom_point(aes(fill = Trt_Genotype),
             shape = 21,
             size = 2,
             alpha = 0.5,
             position = position_dodge(0.3)) +
  scale_x_discrete("") +
  scale_y_continuous("Relative Abundance (%)") +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))

tiff(filename = "tmp/wt_Order_over_time.tiff",
     height = 5,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p0)
graphics.off()

print(p0)
p1 <- ggplot(mu,
             aes(x = x,
                 y = Order,
                 color = Trt_Genotype,
                 shape = Week)) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)")

tiff(filename = "tmp/wt_Order_ra.tiff",
     height = 4,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

ggplotly(p1 +
           theme(legend.position = "none"))

20.2 3. Family

NOTE: only the first 24 families had large enough counts - ploting only them.

mu$Trt_Genotype <- factor(paste(mu$Treatment,
                                mu$Genotype,
                                sep = "_"))
mu1 <- droplevels(mu[Family %in% levels(mu$Family)[nlevels(mu$Family):(nlevels(mu$Family) - 24)], ])

p0 <- ggplot(mu1,
             aes(x = Week,
                 y = x,
                 group = Trt_Genotype)) +
  facet_wrap(~ Family,
             scale = "free_y") +
  geom_line(position = position_dodge(0.3)) +
  geom_point(aes(fill = Trt_Genotype),
             shape = 21,
             size = 2,
             alpha = 0.5,
             position = position_dodge(0.3)) +
  scale_x_discrete("") +
  scale_y_continuous("Relative Abundance (%)") +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))

tiff(filename = "tmp/wt_Family_over_time.tiff",
     height = 7,
     width = 9,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p0)
graphics.off()

print(p0)
p1 <- ggplot(mu1,
             aes(x = x,
                 y = Family,
                 color = Trt_Genotype,
                 shape = Week)) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)") +
  theme(legend.position = "top")

tiff(filename = "tmp/wt_Family_ra.tiff",
     height = 4,
     width = 7,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

ggplotly(p1+
           theme(legend.position = "none"))

20.3 4. Genus

mu$Trt_Genotype <- factor(paste(mu$Treatment,
                                mu$Genotype,
                                sep = "_"))
mu1 <- droplevels(mu[Genus %in% levels(mu$Genus)[nlevels(mu$Genus):(nlevels(mu$Genus) - 35)], ])

p0 <- ggplot(mu1,
             aes(x = Week,
                 y = x,
                 group = Trt_Genotype)) +
  facet_wrap(~ Genus,
             scale = "free_y") +
  geom_line(position = position_dodge(0.3)) +
  geom_point(aes(fill = Trt_Genotype),
             shape = 21,
             size = 2,
             alpha = 0.5,
             position = position_dodge(0.3)) +
  scale_x_discrete("") +
  scale_y_continuous("Relative Abundance (%)") +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))

tiff(filename = "tmp/wt_Genus_over_time.tiff",
     height = 9,
     width = 12,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p0)
graphics.off()

print(p0+
           theme(legend.position = "none"))
p1 <- ggplot(mu1,
             aes(x = x,
                 y = Genus,
                 color = Trt_Genotype,
                 shape = Week)) +
  geom_point(size = 3,
             alpha = 0.5) +
  geom_vline(xintercept = 1,
             linetype = "dashed") +
  scale_x_continuous("Relative Abundance (%)") +
  theme(legend.position = "top")

tiff(filename = "tmp/wt_Genus_ra.tiff",
     height = 9,
     width = 9,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

ggplotly(p1+
           theme(legend.position = "none"))

21 Session Information

sessionInfo()
LS0tCnRpdGxlOiAiRGF0YSBWaXN1YWxpemF0aW9uIG9mIFdUIGFuZCBOcmYyIEtPICgtLy0pIEJMNiBQRUlUQyBvciBDcmFuYmVycnkgVHJlYXRlZCBNaWNlIDE2UyBNaWNyb2Jpb21lIERhdGEgQW5hbHlzaXMsIFNlcHRlbWJlciAyMDE5IEJhdGNoIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCkRhdGU6IGByIGRhdGUoKWAgICAgIApTY2llbnRpc3Q6IFtSYW4gWWluXShtYWlsdG86cnkxNDdAc2NhcmxldG1haWwucnV0Z2Vycy5lZHUpICAgICAgClNlcXVlbmNpbmcgKFdha3NtYW4pOiBbRGlieWVuZHUgS3VtYXJdKG1haWx0bzpka0B3YWtzbWFuLnJ1dGdlcnMuZWR1KSAgICAgIApTdGF0aXN0aWNzOiBbRGF2aXQgU2FyZ3N5YW5dKG1haWx0bzpzYXJnZGF2aWRAZ21haWwuY29tKSAgICAgIApQcmluY2lwYWwgSW52ZXN0aWdhdG9yOiBbQWgtTmcgS29uZ10obWFpbHRvOmtvbmd0QHBoYXJtYWN5LnJ1dGdlcnMuZWR1KSAKCmBgYHt9CiMgVGF4b25vbWljIFJhbmtzOgojICoqSyoqaW5nICoqUCoqaGlsbGlwICoqQyoqYW4gbioqTyoqdCAqKkYqKmluZCAqKkcqKnJlZW4gKipTKipvY2tzCiMgKiBLaW5nZG9tICAgICAgICAgICAgICAgIAojICogUGh5bHVtICAgICAgICAgICAgICAgICAgICAKIyAqIENsYXNzICAgICAgICAgICAgICAgICAgIAojICogT3JkZXIgICAgICAgICAgICAgICAgICAgCiMgKiBGYW1pbHkgICAgIAojICogR2VudXMgICAgIAojICogU3BlY2llcyAgCmBgYAoKYGBge3Igc2V0dXB9CiMgb3B0aW9ucyhzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsCiMgICAgICAgICBzY2lwZW4gPSA5OTkpCgojICMgSW5jcmVhc2UgbW1lbW9yeSBzaXplIHRvIDY0IEdiLS0tLQojIGludmlzaWJsZSh1dGlsczo6bWVtb3J5LmxpbWl0KDY1NTM2KSkKCgojIHN0cihrbml0cjo6b3B0c19jaHVuayRnZXQoKSkKIyAjIE5PVEU6IHRoZSBiZWxvdyBkb2VzIG5vdCB3b3JrIQojIGtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsIAojICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsCiMgICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwKIyAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBGQUxTRSkKCiMgcmVxdWlyZShrbml0cikKIyByZXF1aXJlKGthYmxlRXh0cmEpCiMgcmVxdWlyZShzaGlueSkKCnJlcXVpcmUocGh5bG9zZXEpCnJlcXVpcmUoZGF0YS50YWJsZSkKcmVxdWlyZShnZ3Bsb3QyKQpyZXF1aXJlKHBsb3RseSkKcmVxdWlyZShEVCkKcmVxdWlyZShsbWVyVGVzdCkKcmVxdWlyZShubmV0KQoKc291cmNlKCJzb3VyY2UvZnVuY3Rpb25zX21heTIwMTkuUiIpCgojIE9uIFdpbmRvd3Mgc2V0IG11bHRpdGhyZWFkPUZBTFNFLS0tLQptdCA8LSBUUlVFCmBgYAoKIyBJbnRyb2R1Y3Rpb24KQzU3QkwvNiB3aWxkLXR5cGUgKFdUKSBhbmQgTnJmLTIgZG91YmxlLWtub2NrLW91dCAoS08gLS8tKSBtaWNlIHdlcmUgZ2l2ZW4gMi13ZWVrIG1pY3JvYmlvbWUgc3RhYmlsaXphdGlvbiBwcm9jZXNzIHVzaW5nIEFJTjkzTSBkaWV0IGFuZCA4IG1vcmUgd2Vla3MgdG8gdHJlYXQgd2l0aCBlaXRoZXIgQUlOOTNNIG9yIEFJTjkzTSA1JSBQRUlUQyBkaWV0LiBGZWNhbCBzYW1wbGVzIHdlcmUgY29sbGVjdGVkIHdlZWtseSwgaW1tZWRpYXRlbHkgZnJvemVuIGluIGxpcXVpZCBuaXRyb2dlbiBhbmQgc3RvcmVkIGF0IC04MF5vXkMuIFNlcnVtLCBjZWNhbCwgY29sb24gZXBpdGhlbGlhbCBhbmQgd2hvbGUgY29sb24gdGlzc3VlcyBhdCB3ZWVrIDEwIHdlcmUgYWxzbyBjb2xsZWN0ZWQgZm9yIGZ1cnRoZXIgYW5hbHlzZXMuIEJhc2VsaW5lLCB3ZWVrIDEgYW5kIDQgZmVjYWwgc2FtcGxlcyB3ZXJlIHNlbGVjdGVkIGZvciAxNnMgclJOQSBzZXF1ZW5jaW5nLiAgCiAgClRoaXMgZG9jdW1lbnQgZXhhbWluZXMgcmVzdWx0cyBmcm9tIHRoZSBXVCBtaWNlIHNhbXBsZXMuICAKICAKV2Ugd2lsbCBhdHRhbXB0IHRvIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczogIAoxLiBEaWQgbWljcm9iaW9tZSBjaGFuZ2Ugb3ZlciB0aW1lPyAgCjIuIFdhcyBtaWNyb2Jpb21lIGFmZmVjdGVkIGJ5IGRpZXQ/ICAKMy4gV2FzIHRoZXJlIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBLTyBhbmQgV1Q/ICAKNC4gSWYgdGhlcmUgd2FzIGEgY2hhbmdlIGluIG1pY3JvYmlvbWUgY29tcG9zaXRpb24sIHdoYXQgZnVuY3Rpb25hbCBjaGFuZ2VzIGRpZCBpdCBjYXJyeT8gV2hhdCBhcmUgdGhlIGVzc2VudGlhbCBmdW5jdGlvbnMgb2YgdGhlIGJhY3RlcmlhIGFmZmVjdGVkIGJ5IHRoZSB0cmVhdG1lbnQgYW5kIGhvdyBjYW4gdGhpcyBiZSBzaG93biBpbiB2aXZvIChtZXRhYm9saXRlcywgaW5mbGFtbWF0aW9uIG1hcmtlcnMsIGV0Yy4pPwoKIyBEYXRhIHByZXByb2Nlc3NpbmcKIyMgUmF3IERhdGEgCkZhc3RRIGZpbGVzIHdlcmUgZG93bmxvYWRlZCBmcm9tIFt0aGlzIFJ1dGdlcnMgQm94IGxvY2F0aW9uXShodHRwczovL3J1dGdlcnMuYXBwLmJveC5jb20vZm9sZGVyLzkwMTQzNDYyMjkxKS4gQSB0b3RhbCBvZiAxNDQgZmlsZXMgKDIgcGVyIHNhbXBsZSwgcGFpci1lbmRlZCkgYW5kIGEgcGFpciBvZiB1bmRldGVybWluZWQgcmVhZHMgd2VyZSBkb3dubG9hZGVkLiAKCiMjIFNjcmlwdApUaGlzIHNjcmlwdCAoKioqbnJmMnViaW9tZV9kYWRhMl9zZXAyMDE5X3YxLlJtZCoqKikgd2FzIGRldmVsb3BlZCB1c2luZyBbREFEQTIgUGlwZWxpbmUgVHV0b3JpYWwgKDEuMTIpXShodHRwczovL2JlbmpqbmViLmdpdGh1Yi5pby9kYWRhMi90dXRvcmlhbC5odG1sKSB3aXRoIHRpcHMgYW5kIHRyaWNrcyBmcm9tIHRoZSBbVW5pdmVyc2l0eSBvZiBNYXJ5bGFuZCBTaG9vbCBvZiBNZWRpY2luZSBJbnN0aXR1dGUgZm9yIEdlbm9tZSBTY2llbmNlcyAoSUdTKV0oaHR0cDovL3d3dy5pZ3MudW1hcnlsYW5kLmVkdS8pIFtNaWNyb2Jpb21lIEFuYWx5c2lzIFdvcmtzaG9wIChBcHJpbCA4LTExLCAyMDE5KV0oaHR0cDovL3d3dy5pZ3MudW1hcnlsYW5kLmVkdS9lZHVjYXRpb24vd2tzaHBfbWV0YWdlbm9tZS5waHApLiBUaGUgb3V0cHV0IG9mIHRoZSBEQURBMiBzY3JpcHQgKCoqKmRhdGFfbWF5MjAxOS9wc19zZXAyMDE5LlJEYXRhKioqKSBpcyBleHBsb3JlZCBpbiB0aGlzIGRvY3VtZW50LgoKIyBNZXRhIGRhdGE6IHNhbXBsZSBkZXNjcmlwdGlvbgpgYGB7ciBkYXRhfQojIExvYWQgZGF0YS0tLS0KIyBDb3VudHMKbG9hZCgiZGF0YV9zZXAyMDE5L3BzX3NlcDIwMTkuUkRhdGEiKQoKIyBUYXhvbm9teQpsb2FkKCJkYXRhX3NlcDIwMTkvdGF4YS5SRGF0YSIpCnRheGEgPC0gZGF0YS50YWJsZShzZXExNnMgPSByb3duYW1lcyh0YXhhKSwKICAgICAgICAgICAgICAgICAgIHRheGEpCmBgYAoKKipOT1RFOiBjb3JyZWN0aW9uIHRvIHRoZSBtZXRhLWRhdGEhKiogKDExLzE1LzIwMTkpCmBgYHtyIGNvcnJlY3RfbWV0YV9kYXRhfQpjb3JyZWN0X3NhbXBsZXMgPC0gZnJlYWQoImRhdGFfc2VwMjAxOS8xNnMgbWV0YWRhdGEgU2VwLTIwMTkuY3N2IikKcHNfc2VwMjAxOUBzYW1fZGF0YSREU1MgPC0gY29ycmVjdF9zYW1wbGVzJERTUwpgYGAKCiMgU2FtcGxlcwpgYGB7ciBzYW1wbGVzfQpwc19zZXAyMDE5QHNhbV9kYXRhJEdlbm90eXBlX1dlZWsgPC0gcGFzdGUocHNfc2VwMjAxOUBzYW1fZGF0YSRnZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzX3NlcDIwMTlAc2FtX2RhdGEkdGltZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikKcHNfc2VwMjAxOUBzYW1fZGF0YSRJRCA8LSBmYWN0b3IocGFzdGUwKHBzX3NlcDIwMTlAc2FtX2RhdGEkbWljZV9udW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwc19zZXAyMDE5QHNhbV9kYXRhJGNhZ2UpKQoKcHNfc2VwMjAxOUBzYW1fZGF0YSRUUkVBVE1FTlQgPC0gcGFzdGUwKHBzX3NlcDIwMTlAc2FtX2RhdGEkRFNTLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHNfc2VwMjAxOUBzYW1fZGF0YSRQRUlUQywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzX3NlcDIwMTlAc2FtX2RhdGEkY3JhbmJlcnJ5KQpwc19zZXAyMDE5QHNhbV9kYXRhJFRSRUFUTUVOVCA8LSBmYWN0b3IocHNfc2VwMjAxOUBzYW1fZGF0YSRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCIwMDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMTAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjExMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIxMDEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk5haXZlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEU1MrUEVJVEMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFNTK0NyYW5iZXJyeSIpKQoKc2FtcGxlcyA8LSBwc19zZXAyMDE5QHNhbV9kYXRhCmRhdGF0YWJsZShzYW1wbGVzLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IG5yb3coc2FtcGxlcykpKQpgYGAKCiMgUHJ1bmUgZGF0YQpUaGUgT1RVcyB3ZXJlIG1hcHBlZCB0byBCYWN0ZXJpYSAoOTYuMDclKSwgRXVrYXJ5b3RhICgyLjk1JSkgYW5kIEFyY2hlYSAoMC4wMyUpIGtpbmdkb21zLCBhbmQgIDc1IE9UVXMgKDAuOTUlKSB1bmRlZmluZWQuIAoKYGBge3IgY2hlY2tfbWFwcGluZ19raW5nZG9tLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQp0MSA8LSBkYXRhLnRhYmxlKHRhYmxlKHRheF90YWJsZShwc19zZXAyMDE5KVssICJLaW5nZG9tIl0sCiAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZSA9IE5VTEwpKQp0MSRWMVtpcy5uYSh0MSRWMSldIDwtICJVbmtub3duIgoKdDFbLCBwY3QgOj0gTi9zdW0oTildCnNldG9yZGVyKHQxLCAtTikKCmNvbG5hbWVzKHQxKSA8LSBjKCJLaW5nZG9tIiwKICAgICAgICAgICAgICAgICAgIk51bWJlciBvZiBPVFVzIiwKICAgICAgICAgICAgICAgICAgIlBlcmNlbnQgb2YgT1RVcyIpCmRhdGF0YWJsZSh0MSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIk51bWJlciBvZiBPVFVzIGJ5IEtpbmdkb20iLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDEpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDIsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKClRoZSB0b3RhbCBvZiA3LDg2NyB1bmlxdWUgc2VxdWVuY2VzIHdlcmUgZm91bmQuIE91dCBvZiB0aG9zZSwgNyw1NTggd2VyZSBtYXBwZWQgdG8gYmFjdGVyaWFsIGdlbm9tZXMuIAoKYGBge3Iga2VlcF9iYWN0ZXJpYX0KZGltKHBzX3NlcDIwMTlAb3R1X3RhYmxlQC5EYXRhKQoKIyBSZW1vdmUgT1RVIG5vdCBtYXBwZWQgdG8gQmFjdGVyaWEKcHMwIDwtIHN1YnNldF90YXhhKHBzX3NlcDIwMTksIAogICAgICAgICAgICAgICAgICAgS2luZ2RvbSA9PSAiQmFjdGVyaWEiKQpkaW0ocHMwQG90dV90YWJsZUAuRGF0YSkKYGBgCiAgCk91dCBvZiB0aGUgNyw1NTggT1RVcyA3LDI0NyBiZWxvbmdlZCB0byAxMiBQaHlsYS4gMzExIG9mIHRoZSBPVFVzIChvciA0LjExJSBvZiBiYWN0ZXJpYWwgT1RVcykgY291bGQgbm90IGJlIG1hcHBlZCB0byBhIHBoeWx1bS4KCmBgYHtyIHBoeWx1bV9tYXBwaW5nfQp0MiA8LSBkYXRhLnRhYmxlKHRhYmxlKHRheF90YWJsZShwczApWywgIlBoeWx1bSJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZSA9IE5VTEwpKQp0MiRWMVtpcy5uYSh0MiRWMSldIDwtICJVbmtub3duIgpzZXRvcmRlcih0MiwgLU4pCnQyWywgcGN0IDo9IE4vc3VtKE4pXQpzZXRvcmRlcih0MiwgLU4pCgpjb2xuYW1lcyh0MikgPC0gYygiUGh5bHVtIiwKICAgICAgICAgICAgICAgICAgIk51bWJlciBvZiBPVFVzIiwKICAgICAgICAgICAgICAgICAgIlBlcmNlbnQgb2YgT1RVcyIpCgpkYXRhdGFibGUodDIsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJOdW1iZXIgb2YgQmFjdGVyaWFsIE9UVXMgYnkgUGh5bHVtIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHQyKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSAyLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAzLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMikKYGBgCgojIE9UVSB0YWJsZSAoZmlyc3QgMTAgcm93cykKYGBge3Igb3R1X3RhYmxlLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0Kb3R1IDwtIGRhdGEudGFibGUocHMwQHRheF90YWJsZUAuRGF0YSwKICAgICAgICAgICAgICAgICAgdChwczBAb3R1X3RhYmxlQC5EYXRhKSkKZGF0YXRhYmxlKGhlYWQob3R1LCAxMCksCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSA3OjM2LAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKQpgYGAKCiMgVG90YWwgY291bnRzIHBlciBzYW1wbGUgKGkuZS4gc2VxdWVuY2luZyBkZXB0aCkKYGBge3Igc2VxX2RlcHRoLCBmaWcud2lkdGggPSAxMCxmaWcuaGVpZ2h0ID0gNX0KdDEgPC0gY29sU3VtcyhvdHVbLCA3Om5jb2wob3R1KV0pCnQxIDwtIGRhdGEudGFibGUoU0FNUExFX05BTUUgPSBuYW1lcyh0MSksCiAgICAgICAgICAgICAgICAgVG90YWwgPSB0MSkKCnQyIDwtIGRhdGEudGFibGUoU0FNUExFX05BTUUgPSByb3duYW1lcyhzYW1wbGVzKSwKICAgICAgICAgICAgICAgICBJRCA9IHNhbXBsZXMkSUQsCiAgICAgICAgICAgICAgICAgQ0FHRSA9IHNhbXBsZXMkY2FnZSwKICAgICAgICAgICAgICAgICBUUkVBVE1FTlQgPSBzYW1wbGVzJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICBHZW5vdHlwZSA9IHNhbXBsZXMkZ2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgV0VFSyA9IHNhbXBsZXMkdGltZSkKCnNtcGwgPC0gbWVyZ2UodDEsCiAgICAgICAgICAgICAgdDIsCiAgICAgICAgICAgICAgYnkgPSAiU0FNUExFX05BTUUiKQoKcDEgPC0gZ2dwbG90KHNtcGwsCiAgICAgICAgICAgICBhZXMoeCA9IFNBTVBMRV9OQU1FLAogICAgICAgICAgICAgICAgIHkgPSBUb3RhbCwKICAgICAgICAgICAgICAgICBmaWxsID0gVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIGNvbG91ciA9IFdFRUspKSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV94IikgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiTnVtYmVyIG9mIFJlYWRzIikgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUoIlRyZWF0bWVudCIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpIApnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBzZXFfZGVwdGhfZ3JleXNjYWxlLCAsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQgPSA2fQp0bXAgPC0gY29weShzbXBsKQp0bXAkV0VFSyA8LSBmYWN0b3IodG1wJFdFRUssCiAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYmFzZWxpbmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlZWsxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3ZWVrOCIpLAogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIldlZWsgMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXZWVrIDgiKSkKdG1wJEdlbm90eXBlIDwtIGZhY3Rvcih0bXAkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygid2lkZXR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5yZjJLTyIpLAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIldpbGQgVHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTnJmMiBLTyIpKQpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgZmlsbCA9IFRSRUFUTUVOVCkpICsKICBmYWNldF93cmFwKH4gR2Vub3R5cGUgKyBXRUVLLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV94IikgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIk51bWJlciBvZiBSZWFkcyIpICsKICBzY2FsZV9maWxsX2dyZXkoIlRyZWF0bWVudCIsIAogICAgICAgICAgICAgICAgICBzdGFydCA9IDAuMSwgCiAgICAgICAgICAgICAgICAgIGVuZCA9IDEsCiAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInJlZCIsCiAgICAgICAgICAgICAgICAgIGFlc3RoZXRpY3MgPSAiZmlsbCIpICsKICB0aGVtZV9idygpICsgCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCgp0aWZmKGZpbGVuYW1lID0gInRtcC9zZXFfZGVwdGgudGlmZiIsCiAgICAgaGVpZ2h0ID0gNiwKICAgICB3aWR0aCA9IDYsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDEpCmBgYAoKIyBSaWNobmVzcyAoQWxwaGEgZGl2ZXJzaXR5KQpTaGFubm9uIGluZGV4IChha2EgU2hhbm5vbiBlbnRocm9waHkpIGlzIGNhbGN1bGF0ZWQgYXM6ICAKSCcgPSAtc3VtKDEgdG8gUilwKGkpbG4ocChpKSkgCldoZW4gdGhlcmUgaXMgZXhhY3RseSAxIHR5cGUgb2YgZGF0YSAoZS5nLiBhIHNpbmdsZSBzcGVjaWVzIGluIHRoZSBzYW1wbGUpLCBIJz0wLiBUaGUgb3Bwb3NpdGUgc2NlbmFyaW8gaXMgd2hlbiB0aGVyZSBhcmUgUj4xIHNwZWNpZXMgcHJlc2VudCBpbiB0aGUgc2FtcGxlIGluIHRoZSBleGFjdCBzYW1lIGFtb3VudHMgYW5kIEgnPWxuKFIpLiAgCiAgClNoYW5ub24ncyBkaXZlcnNpdHkgaW5kZXggd2FzIGNhbGN1bGF0ZWQgZm9yIGVhY2ggc2FtcGxlIGFuZCBwbG90ZWQgb3ZlciB0aW1lIHVzaW5nIHRoZSA3LDc2NCBmcm9tIHRoZSAxMyBQaHlsdW0gYWJvdmUuCiAgCmBgYHtyIHNoYW5ub25fdnNfZGVwdGgsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA2fQpzaGFubm9uLm5keCA8LSBlc3RpbWF0ZV9yaWNobmVzcyhwczAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmVzID0gIlNoYW5ub24iKQoKc2hhbm5vbi5uZHggPC0gZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHJvd25hbWVzKHNoYW5ub24ubmR4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzaGFubm9uLm5keCkKCnNtcGwgPC0gbWVyZ2Uoc21wbCwKICAgICAgICAgICAgICBzaGFubm9uLm5keCwKICAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgpwMSA8LSBnZ3Bsb3Qoc21wbCwKICAgICAgICAgICAgIGFlcyh4ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgeSA9IFNoYW5ub24sCiAgICAgICAgICAgICAgICAgZmlsbCA9IEdlbm90eXBlLAogICAgICAgICAgICAgICAgIHNoYXBlID0gV0VFSykpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKGJyZWFrcyA9IHVuaXF1ZShzbXBsJFdFRUspLAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSAyMToyMykKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3NoYW5ub25fdnNfZGVwdGgudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDYsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKZ2dwbG90bHkocDEpCmBgYAoKRXZlbiB0aG91Z2ggKioqZXN0aW1hdGVfcmljaG5lc3MqKiogZnVuY3Rpb24gZG9lcyBub3QgYWRqdXN0IGZvciB0aGUgc2VxdWVuY2luZyBkZXB0aCwgdGhlcmUgaXMgbm8gY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgaW5kZXggYW5kIHRoZSBzYW1wbGUncyBzZXF1ZWNpbmcgZGVwdGguIFByb2NlZWQgd2l0aCB0aGUgY29tcGFyaXNvbi4KCiMgU2hhbm5vbiBpZGV4IG92ZXIgdGltZQpgYGB7ciByaWNobmVzcywgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDV9CnAxIDwtIHBsb3RfcmljaG5lc3MocHMwLAogICAgICAgICAgICAgICAgICAgIHggPSAidGltZSIsIAogICAgICAgICAgICAgICAgICAgIG1lYXN1cmVzID0gIlNoYW5ub24iKSArCiAgZmFjZXRfd3JhcCh+IGdlbm90eXBlKSArCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IElEKSwKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IFRSRUFUTUVOVCksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAxKSkKCmdncGxvdGx5KHAgPSBwMSwKICAgICAgICAgdG9vbHRpcCA9IGMoIklEIiwKICAgICAgICAgICAgICAgICAgICAgInZhbHVlIikpCgpwMSA8LSBwMSArIAogIHNjYWxlX2ZpbGxfZGlzY3JldGUoIiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3NoYW5ub24udGlmZiIsCiAgICAgaGVpZ2h0ID0gNCwKICAgICB3aWR0aCA9IDUsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQpgYGAKClRoZSBwbG90IGFib3ZlIHN1Z2dlc3RzIHRoYXQgdGhlIGxhcmdlc3QgZGlmZmVyZW5jZXMgaW4gYWxwaGEgZGl2ZXJzaXR5IChhcyBtZWFzdXJlZCBieSBTaGFubm9uJ3MgaW5kZXgpIGFyZSBpbiBnZW5vdHlwZS4KCiMgQXZlcmFnZSBTaGFubm9uIEluZGV4CmBgYHtyIGF2Z19zaGFubm9uX3Bsb3QsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA1fQojIEF2ZXJhZ2Ugc2hhbm5vbiBpbmRleCBieSB0cmVhdG1lbnQgZ3JvdXAKdG1wIDwtIGNvcHkoc21wbCkKCnRtcFssIG11IDo9IG1lYW4oU2hhbm5vbiksCiAgICBieSA9IGxpc3QoVFJFQVRNRU5ULAogICAgICAgICAgICAgIEdlbm90eXBlLAogICAgICAgICAgICAgIFdFRUspXQp0bXBbLCBzZW0gOj0gc2QoU2hhbm5vbikvc3FydCguTiksCiAgICBieSA9IGxpc3QoVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIEdlbm90eXBlLAogICAgICAgICAgICAgICAgIFdFRUspXQp0bXAgPC0gdW5pcXVlKHRtcFssIGMoIlRSRUFUTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgICAiR2Vub3R5cGUiLAogICAgICAgICAgICAgICAgICAgICAgIldFRUsiLAogICAgICAgICAgICAgICAgICAgICAgIm11IiwKICAgICAgICAgICAgICAgICAgICAgICJzZW0iKV0pCnRtcCRXRUVLIDwtIGZhY3Rvcih0bXAkV0VFSywKICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJhc2VsaW5lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlZWsxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIndlZWs4IiksCiAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJXZWVrIDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldlZWsgOCIpKQp0bXAkR2Vub3R5cGUgPC0gZmFjdG9yKHRtcCRHZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJ3aWRldHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibnJmMktPIiksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiV2lsZCBUeXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOcmYyIEtPIikpCgpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBXRUVLLAogICAgICAgICAgICAgICAgIHkgPSBtdSwKICAgICAgICAgICAgICAgICB5bWluID0gbXUgLSBzZW0sCiAgICAgICAgICAgICAgICAgeW1heCA9IG11ICsgc2VtLAogICAgICAgICAgICAgICAgIGZpbGwgPSBUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUUkVBVE1FTlQpKSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlKSArCiAgZ2VvbV9lcnJvcmJhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNCksCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuNCkgKwogIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC40KSkgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIlNoYW5ub24gSW5kZXgiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKCnRpZmYoZmlsZW5hbWUgPSAidG1wL2F2Z19zaGFubm9uLnRpZmYiLAogICAgIGhlaWdodCA9IDUsCiAgICAgd2lkdGggPSA2LAogICAgIHVuaXRzID0gImluIiwKICAgICByZXMgPSA2MDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCnByaW50KHAxKQpgYGAKICAKVGVzdCBpZiB0aGUgcmljaG5lc3MgY2hhbmdlZCBiZXR3ZWVuIHRoZSBiYXNlbGluZSBhbmQgV2VlayA4LiAgCiAgCmBgYHtyIGxtX3JpY2huZXNzfQpzbXBsJFRSRUFUTUVOVCA8LSBmYWN0b3Ioc21wbCRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEU1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmFpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFNTK1BFSVRDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytDcmFuYmVycnkiKSkKCnRtcCA8LSBkcm9wbGV2ZWxzKHNtcGxbV0VFSyAhPSAid2VlazEiXSkKCm0xIDwtIGxtKFNoYW5ub24gIH4gV0VFSyooVFJFQVRNRU5UICsgR2Vub3R5cGUpLAogICAgICAgICAjIG9mZnNldCA9IFRvdGFsLAogICAgICAgICBkYXRhID0gdG1wKQpzdW1tYXJ5KG0xKQpgYGAKICAKYGBge3IgbG1lcl9yaWNobmVzc30KbTIgPC0gbG1lcihTaGFubm9uICB+IFdFRUsqKFRSRUFUTUVOVCArIEdlbm90eXBlKSArICgxIHwgSUQpLAogICAgICAgICAgICMgb2Zmc2V0ID0gVG90YWwsCiAgICAgICAgICAgZGF0YSA9IHRtcCkKc3VtbWFyeShtMikKYGBgCgojIENhbGN1bGF0ZSBjaGFuZ2UgaW4gU2hhbm5vbiBpbmRleCBmcm9tIGJhc2VsaW5lCmBgYHtyIGRlbHRhX3NoYW5ub24sIGZpZy53aWR0aCA9IDcsIGZpZy5oZWlnaHQgPSA1fQpkZCA8LSBzbXBsCmRkWywgZGVsdGEgOj0gU2hhbm5vbiAtIFNoYW5ub25bV0VFSyA9PSAiYmFzZWxpbmUiXSwKICAgYnkgPSBJRF0KZGQkZGlmZiA8LSBwYXN0ZShkZCRXRUVLLAogICAgICAgICAgICAgICAgICItYmFzZWxpbmUiLAogICAgICAgICAgICAgICAgIHNlcCA9ICIiKQoKZGQgPC0gZGRbV0VFSyAhPSAiYmFzZWxpbmUiLF0KCnAxIDwtIGdncGxvdChkZCwKICAgICAgICAgICAgIGFlcyh4ID0gVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgIHkgPSBkZWx0YSwKICAgICAgICAgICAgICAgICBmaWxsID0gR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IGRpZmYpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLAogICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJTaGFubm9uIEluZGV4IFBlcmNlbnQgQ2hhbmdlIGZyb20gQmFzZWxpbmUiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQpwcmludChwMSkKCmRkJFRSRUFUTUVOVCA8LSBmYWN0b3IoZGQkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEU1MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOYWl2ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytQRUlUQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytDcmFuYmVycnkiKSkKZGQkR2Vub3R5cGUgPC0gZmFjdG9yKGRkJEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIndpZGV0eXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJucmYyS08iKSkKCm0xIDwtIGxtKGRlbHRhIH4gVFJFQVRNRU5UKkdlbm90eXBlLAogICAgICAgICBkYXRhID0gZGQpCnN1bW1hcnkobTEpCgojIE5vIHNpZ25pZmljYW50IGludGVyYWN0aW9ucywgcHJvY2VlZCB3aXRoIDItd2F5IGFuYWx5c2lzCm0yIDwtIGxtKGRlbHRhIH4gVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgIGRhdGEgPSBkZCkKc3VtbWFyeShtMikKYGBgCgpBdCBXZWVrIDggdGhlcmUgd2FzIHNpZ25pZmljYW50bHkgc21hbGxlciBpbmNyZWFzZSBvZiBhbHBoYSBkaXZlcnNpdHkgZnJvbSBiYXNlbGluZSBpbiBOcmYyIEtPIGNvbXBhcmVkIHRvIFdULCBhbmQgaW4gRFNTK0NyYW5iZXJyeSBjb21wYXJlZCB0byBEU1Mgb25seS4KCiMgTG9hZCBhbWlub2FjaWRzCmBgYHtyIGFtaW5vYWNpZHNfZGF0YX0KYWEgPC0gZnJlYWQoImRhdGFfc2VwMjAxOS9zZXAyMDE5X2FtaW5vYWNpZHMuY3N2IikKCmFhIDwtIGFhWyFpcy5uYShJRCksIF0KYWEkSUQgPC0gcGFzdGUwKGFhJElELAogICAgICAgICAgICAgICAgYWEkQ0FHRSkKCnNtcGwxIDwtIHVuaXF1ZShzbXBsWywgYygiSUQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRSRUFUTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR2Vub3R5cGUiKV0pCnNtcGwxJElEIDwtIGFzLmNoYXJhY3RlcihzbXBsMSRJRCkKYWEgPC0gbWVyZ2Uoc21wbDEsCiAgICAgICAgICAgIGFhLAogICAgICAgICAgICBieSA9ICJJRCIpCmFhWywgdHJ0X3dlZWsgOj0gcGFzdGUoVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgIFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIl8iKV0KYWEkdHJ0X3dlZWsgPC0gZmFjdG9yKGFhJHRydF93ZWVrLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTmFpdmVfd2VlazIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmFpdmVfd2VlazYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFNTX3dlZWsyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTU193ZWVrNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEU1MrQ3JhbmJlcnJ5X3dlZWsyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytDcmFuYmVycnlfd2VlazYiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRTUytQRUlUQ193ZWVrMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEU1MrUEVJVENfd2VlazYiKSkKYGBgCgojIEFtaW5vYWNpZHMgYnkgYW5pbWFsLCB0cmVhdG1lbnQgZ3JvdXAgYW5kIHRpbWVwb2ludApgYGB7ciBhbWlub2FjaWRzX3Bsb3RzLCBmaWcuaGVpZ2h0ID0gNCwgZmlnLndpZHRoID0gNX0KZm9yIChpIGluIDg6KG5jb2woYWEpIC0gMSkpIHsKICB0bXAgPC0gYWFbLCBjKDEsIDMsIDcsIG5jb2woYWEpLCBpKSwgd2l0aCA9IEZBTFNFXQogIGNvbG5hbWVzKHRtcClbNV0gPC0gIlkiCiAgcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgICAgYWVzKHggPSB0cnRfd2VlaywKICAgICAgICAgICAgICAgICAgIHkgPSBZLAogICAgICAgICAgICAgICAgICAgZmlsbCA9IEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBJRCkpICsKICAgIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwKICAgICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogICAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGNvbG5hbWVzKGFhKVtpXSkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCiAgIyB0aWZmKGZpbGVuYW1lID0gcGFzdGUwKCJ0bXAvIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgY29sbmFtZXMoYWEpW2ldLAogICMgICAgICAgICAgICAgICAgICAgICAgICAiLnRpZmYiKSwKICAjICAgICAgaGVpZ2h0ID0gNCwKICAjICAgICAgd2lkdGggPSA1LAogICMgICAgICB1bml0cyA9ICJpbiIsCiAgIyAgICAgIHJlcyA9IDYwMCwKICAjICAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQogICMgcHJpbnQocDEpCiAgIyBncmFwaGljcy5vZmYoKQogIAogIHByaW50KHAxKQp9CmBgYAoKIyBBbWlub2FjaWRzIG92ZXIgdGltZSwgZ3JvdXAgYXZlcmFnZXMKYGBge3IgYW1pbm9hY2lkc19hdmdfcGxvdHMsIGZpZy5oZWlnaHQgPSA0LCBmaWcud2lkdGggPSA1fQpvdXQgPC0gbGlzdCgpCmZvciAoaSBpbiA4OjI3KSB7CiAgdG1wIDwtIGFhWywgYygyLCAzLCA3LCBpKSwgCiAgICAgICAgICAgIHdpdGggPSBGQUxTRV0KICBuYW1lcyh0bXApWzRdIDwtICJ2YWwiCiAgCiAgdG1wWywgbXUgOj0gbWVhbih2YWwsCiAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUpLAogICAgICBieSA9IGxpc3QoVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgR2Vub3R5cGUsCiAgICAgICAgICAgICAgICBXRUVLKV0KICB0bXBbLCBzZW0gOj0gc2QodmFsLAogICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUpL3NxcnQoLk4pLAogICAgICBieSA9IGxpc3QoVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgR2Vub3R5cGUsCiAgICAgICAgICAgICAgICBXRUVLKV0KICBvdXRbW2kgLSA3XV0gPC0gZGF0YS50YWJsZShBbWlub2FjaWQgPSBuYW1lcyhhYSlbaV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pcXVlKHRtcFssIGMoIlRSRUFUTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdlbm90eXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV0VFSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm11IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic2VtIildKSkKfQptdWFhIDwtIHJiaW5kbGlzdChvdXQpCm11YWEkQW1pbm9hY2lkIDwtIGZhY3RvcihtdWFhJEFtaW5vYWNpZCwKICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHVuaXF1ZShtdWFhJEFtaW5vYWNpZCkpCm11YWEkR2Vub3R5cGUgPC0gZmFjdG9yKG11YWEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIndpZGV0eXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibnJmMktPIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIldpbGQgVHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5yZjIgS08iKSkKCmZvciAoaSBpbiAxOm5sZXZlbHMobXVhYSRBbWlub2FjaWQpKSB7CiAgcDEgPC0gZ2dwbG90KG11YWFbQW1pbm9hY2lkID09IGxldmVscyhtdWFhJEFtaW5vYWNpZClbaV0sIF0sCiAgICAgICAgICAgICAgIGFlcyh4ID0gV0VFSywKICAgICAgICAgICAgICAgICAgIHkgPSBtdSwKICAgICAgICAgICAgICAgICAgIHltaW4gPSBtdSAtIHNlbSwKICAgICAgICAgICAgICAgICAgIHltYXggPSBtdSArIHNlbSwKICAgICAgICAgICAgICAgICAgIGZpbGwgPSBUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICBncm91cCA9IFRSRUFUTUVOVCkpICsKICAgIGZhY2V0X3dyYXAofiBHZW5vdHlwZSkgKwogICAgZ2VvbV9lcnJvcmJhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNCksCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC40KSArCiAgICBnZW9tX2xpbmUocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjQpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNCkpICsKICAgIHNjYWxlX3hfZGlzY3JldGUoIiIsCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoIndlZWsyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2VlazYiKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiV2VlayAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayA2IikpICsKICAgIHNjYWxlX3lfY29udGludW91cyhsZXZlbHMobXVhYSRBbWlub2FjaWQpW2ldKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSwKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKICAKICAjIHRpZmYoZmlsZW5hbWUgPSBwYXN0ZTAoInRtcC9hdmdfIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzKG11YWEkQW1pbm9hY2lkKVtpXSwKICAjICAgICAgICAgICAgICAgICAgICAgICAgIi50aWZmIiksCiAgIyAgICAgIGhlaWdodCA9IDUsCiAgIyAgICAgIHdpZHRoID0gNiwKICAjICAgICAgdW5pdHMgPSAiaW4iLAogICMgICAgICByZXMgPSA2MDAsCiAgIyAgICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKICAjIHByaW50KHAxKQogICMgZ3JhcGhpY3Mub2ZmKCkKICAKICBwcmludChwMSkKfQpgYGAKCiMgQW1pbm9hY2lkIGRhdGEgUENBCmBgYHtyIGFtaW5vYWNpZHNfcGNhfQpkdF9wY2EgPC0gYWFbLCBBbGFuaW5lOmdsdXRhbWluZV0KCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gVFJVRSwKIyAgICAgICAgICAgICAgc2NhbGUuID0gVFJVRSkKCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gRkFMU0UsCiMgICAgICAgICAgICAgIHNjYWxlLiA9IEZBTFNFKQoKbTEgPC0gcHJjb21wKGR0X3BjYSkKCnN1bW1hcnkobTEpCgoKIyBTZWxlY3QgUEMtcyB0byBwbGlvdCAoUEMxICYgUEMyKQpjaG9pY2VzIDwtIDE6MgojIFNjb3JlcywgaS5lLiBwb2ludHMgKGRmLnUpCmR0LnNjciA8LSBkYXRhLnRhYmxlKG0xJHhbLCBjaG9pY2VzXSkKIyBBZGQgZ3JvdXBpbmcgdmFyaWFibGUKZHQuc2NyJGdycCA8LSBhYSR0cnRfd2VlawpkdC5zY3IkVFJFQVRNRU5UIDwtIGFhJFRSRUFUTUVOVApkdC5zY3IkV0VFSyA8LSBhYSRXRUVLCmR0LnNjcgoKIyBMb2FkaW5ncywgaS5lLiBhcnJvd3MgKGRmLnYpCmR0LnJvdCA8LSBhcy5kYXRhLmZyYW1lKG0xJHJvdGF0aW9uWywgY2hvaWNlc10pCmR0LnJvdCRmZWF0IDwtIHJvd25hbWVzKGR0LnJvdCkKZHQucm90IDwtIGRhdGEudGFibGUoZHQucm90KQpkdC5yb3QKCmR0LmxvYWQgPC0gbWVsdC5kYXRhLnRhYmxlKGR0LnJvdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9ICJmZWF0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gInBjIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJsb2FkaW5nIikKZHQubG9hZCRmZWF0IDwtIGZhY3RvcihkdC5sb2FkJGZlYXQsCiAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKGR0LmxvYWQkZmVhdCkpCiMgUGxvdCBsb2FkaW5ncwpwMCA8LSBnZ3Bsb3QoZGF0YSA9IGR0LmxvYWQsCiAgICAgICAgICAgICBhZXMoeCA9IGZlYXQsCiAgICAgICAgICAgICAgICAgeSA9IGxvYWRpbmcpKSArCiAgZmFjZXRfd3JhcCh+IHBjLAogICAgICAgICAgICAgbnJvdyA9IDIpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBDIExvYWRpbmdzIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKdGlmZihmaWxlbmFtZSA9ICJ0bXAvcGMuMS4yX2xvYWRpbmdzLnRpZmYiLAogICAgIGhlaWdodCA9IDUsCiAgICAgd2lkdGggPSA4LAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMCkKZ3JhcGhpY3Mub2ZmKCkKCnByaW50KHAwKQpgYGAKCmBgYHtyIGFtaW5vYWNpZHNfcGNhX2F4ZXN9CiMgQXhpcyBsYWJlbHMKdS5heGlzLmxhYnMgPC0gcGFzdGUoY29sbmFtZXMoZHQucm90KVsxOjJdLCAKICAgICAgICAgICAgICAgICAgICAgc3ByaW50ZignKCUwLjFmJSUgZXhwbGFpbmVkIHZhci4pJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAwKm0xJHNkZXZbY2hvaWNlc11eMi9zdW0obTEkc2Rldl4yKSkpCnUuYXhpcy5sYWJzCmBgYAoKYGBge3IgYW1pbm9hY2lkc19iaXBsb3QsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KIyB2YXIua2VlcC5uZHggPC0gd2hpY2goZHQucm90JGZlYXQgJWluJSBjKC4uLikpCiMgT3Igc2VsZWN0IGFsbAojIHZhci5rZWVwLm5keCA8LSAzOm5jb2woZHQxKQojIFVzZSBkdC5yb3RbdmFyLmtlZXAubmR4LF0gYW5kIGR0LnJvdCRmZWF0W3Zhci5rZWVwLm5keF0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gZ3JwKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwKICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IDEwKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSAxMCpQQzIpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMS8yLCAncGljYXMnKSksCiAgICAgICAgICAgICAgICMgc2l6ZSA9IDEsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3RleHQoYWVzKHggPSAxMSpQQzEsCiAgICAgICAgICAgICAgICB5ID0gMTEqUEMyLAogICAgICAgICAgICAgICAgbGFiZWwgPSBkdC5yb3QkZmVhdCksCiAgICAgICAgICAgICMgc2l6ZSA9IDUsCiAgICAgICAgICAgIGhqdXN0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHUuYXhpcy5sYWJzWzFdKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHUuYXhpcy5sYWJzWzJdKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkdyb3VwIikgKwogIGdndGl0bGUoIkJpcGxvdCBvZiBBbWlub2FjaWRzIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMjApKQp0aWZmKGZpbGVuYW1lID0gInRtcC9hbWlub2FjaWRzX2JpcGxvdC50aWZmIiwKICAgICBoZWlnaHQgPSAxMCwKICAgICB3aWR0aCA9IDEwLAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIGFtaW5vYWNpZHNfYmlwbG90X2J5X3dlZWssIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CnAyIDwtIGdncGxvdChkYXRhID0gZHQucm90LAogICAgICAgICAgICAgYWVzKHggPSBQQzEsCiAgICAgICAgICAgICAgICAgeSA9IFBDMikpICsKICBjb29yZF9lcXVhbCgpICsKICBnZW9tX3BvaW50KGRhdGEgPSBkdC5zY3IsCiAgICAgICAgICAgICBhZXMoZmlsbCA9IFdFRUspLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLAogICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gMTAqUEMxLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IDEwKlBDMiksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgxLzIsICdwaWNhcycpKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDEuMiwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fdGV4dChhZXMoeCA9IDExKlBDMSwKICAgICAgICAgICAgICAgIHkgPSAxMSpQQzIsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGR0LnJvdCRmZWF0KSwKICAgICAgICAgICAgIyBzaXplID0gNSwKICAgICAgICAgICAgaGp1c3QgPSAwLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMV0pICsKICBzY2FsZV95X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMl0pICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiV2VlayIpICsKICBnZ3RpdGxlKCJCaXBsb3Qgb2YgQW1pbm9hY2lkcyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIwKSkKdGlmZihmaWxlbmFtZSA9ICJ0bXAvYW1pbm9hY2lkc19ieV93ZWVrX2JpcGxvdC50aWZmIiwKICAgICBoZWlnaHQgPSAxMCwKICAgICB3aWR0aCA9IDEwLAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMikKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAyKQpgYGAKCmBgYHtyIGFtaW5vYWNpZHNfYmlwbG90X2J5X3RydCwgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KcDIgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gVFJFQVRNRU5UKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwKICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IDEwKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSAxMCpQQzIpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMS8yLCAncGljYXMnKSksCiAgICAgICAgICAgICAgIHNpemUgPSAxLjIsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3RleHQoYWVzKHggPSAxMSpQQzEsCiAgICAgICAgICAgICAgICB5ID0gMTEqUEMyLAogICAgICAgICAgICAgICAgbGFiZWwgPSBkdC5yb3QkZmVhdCksCiAgICAgICAgICAgICMgc2l6ZSA9IDUsCiAgICAgICAgICAgIGhqdXN0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHUuYXhpcy5sYWJzWzFdKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHUuYXhpcy5sYWJzWzJdKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIlRyZWF0bWVudCIpICsKICBnZ3RpdGxlKCJCaXBsb3Qgb2YgQW1pbm9hY2lkcyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIwKSkKdGlmZihmaWxlbmFtZSA9ICJ0bXAvYW1pbm9hY2lkc19ieV90cnRfYmlwbG90LnRpZmYiLAogICAgIGhlaWdodCA9IDEwLAogICAgIHdpZHRoID0gMTAsCiAgICAgdW5pdHMgPSAnaW4nLAogICAgIHJlcyA9IDMwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAyKQpncmFwaGljcy5vZmYoKQoKZ2dwbG90bHkocDIpCmBgYAojIFJlbW92ZSB1bm1hcHBlZCBPVFVzClRoZSAzMTEgdW5tYXBwZWQgT1RVcyB3ZXJlIHJlbW92ZWQgZnJvbSBmdXJ0aGVyIGFuYWx5c2lzICh3aXRoIDcsMjQ3IE9UVXMgbGVmdCkuCmBgYHtyIHJlbW92ZV91bm1hcHBlZF9vdHVfcGh5bHVtfQpwczEgPC0gc3Vic2V0X3RheGEocHMwLCAKICAgICAgICAgICAgICAgICAgICFpcy5uYShQaHlsdW0pKQpkaW0ocHMxQG90dV90YWJsZUAuRGF0YSkKYGBgCgojIENvdW50cyBhdCBQaHlsdW0gbGV2ZWwKYGBge3IgY291bnRzX3AsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQpjb3VudHNfcCA8LSBjb3VudHNfYnlfdGF4X3JhbmsoZHQxID0gb3R1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJQaHlsdW0iKQpzZXRvcmRlcihjb3VudHNfcCwgLWAxOTA5MTktMDFgKQpkYXRhdGFibGUoY291bnRzX3AsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KGNvdW50c19wKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSAyOm5jb2woY291bnRzX3ApLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKQpgYGAKCiMgUmVsYXRpdmUgYWJ1bmRhbmNlICglKSBhdCBQaHlsdW0gbGV2ZWwKYGBge3IgcmFfcCwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CnJhX3AgPC0gcmFfYnlfdGF4X3JhbmsoY291bnRzID0gY291bnRzX3AsCiAgICAgICAgICAgICAgICAgICAgICAgcGN0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgZGlnaXQgPSA0KQoKZGF0YXRhYmxlKHJhX3AsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHJhX3ApKSkgJT4lCiAgZm9ybWF0UGVyY2VudGFnZShjb2x1bW5zID0gMjpuY29sKGNvdW50c19wKSwKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKUmVtb3ZlIHBoeWxhIHdpdGggcmVsYXRpdmUgYWJ1bmRhbmNlIG9mID49IDElIGluIGxlc3MgdGhhbiAxMCUgb2Ygc2FtcGxlcy4KCmBgYHtyIHByZXZfcH0KdDEgPC0gZGF0YS50YWJsZShQaHlsdW0gPSByYV9wJFBoeWx1bSwKICAgICAgICAgICAgICAgICBgTnVtYmVyIG9mIFNhbXBsZXNgID0gcm93U3VtcyhyYV9wWywgMjpuY29sKHJhX3ApXSA+PSAwLjAxKSkKdDEkYFBlcmNlbnQgU2FtcGxlc2AgPC0gIHQxJGBOdW1iZXIgb2YgU2FtcGxlc2AvNzIKCnNldG9yZGVyKHQxLCAtYE51bWJlciBvZiBTYW1wbGVzYCkKZGF0YXRhYmxlKHQxLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyh0MSkpKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAzLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMSkKYGBgCgpXZSB3aWxsIHJlbW92ZSBDaGxhbXlkaWFlIGZyb20gdGhpcyBhbmFseXNpcy4KCmBgYHtyIGtlZXBfcGh5bGEsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQprZWVwX3AgPC0gdDEkUGh5bHVtW3QxJGBQZXJjZW50IFNhbXBsZXNgID49IDAuMV0KIyAjIEtlZXAgYWxsCiMga2VlcF9wIDwtIHQxJFBoeWx1bQoKcGFzdGUwKGtlZXBfcCwgY29sbGFwc2UgPSAiLCAiKQoKcHMxIDwtIHN1YnNldF90YXhhKHBzMCwgCiAgICAgICAgICAgICAgICAgICBQaHlsdW0gJWluJSBrZWVwX3AgKQpvdHUxIDwtIGRhdGEudGFibGUocHMxQHRheF90YWJsZUAuRGF0YSwKICAgICAgICAgICAgICAgICAgIHQocHMxQG90dV90YWJsZUAuRGF0YSkpCgpkYXRhdGFibGUoaGVhZChvdHUxLCAxMCksCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSA3Om5jb2wob3R1MSksCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApCmBgYAoKNywyMjQgT1RVcywgZG93biBmcm9tIDcsMjQ3IE9UVXMgaW4gdGhlIHByZXZpb3VzIHRhYmxlLgoKIyBSZWxhdGl2ZSBBYnVuZGFuY2UgaW4gU2FtcGxlcyBhdCBEaWZmZXJlbnQgVGF4b25vbWljIFJhbmtzCiMjIDEuIENsYXNzCmBgYHtyIGNvdW50c19jLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0xNX0KY291bnRzX2MgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIkNsYXNzIikKcmFfYyA8LSByYV9ieV90YXhfcmFuayhjb3VudHNfYykKCnRheC5yYW5rcyA8LSB1bmlxdWUob3R1MVssIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNsYXNzIildKQoKcmFfYyA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfYywKICAgICAgICAgICAgICBieSA9ICJDbGFzcyIpCgp0b3RhbCA8LSByb3dTdW1zKHJhX2NbLCAzOm5jb2wocmFfYyldKQoKcmFfYyRDbGFzcyA8LSBmYWN0b3IocmFfYyRDbGFzcywKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfYyRDbGFzc1tvcmRlcih0b3RhbCldKQoKcmFfYyRQaHlsdW0gPC0gZmFjdG9yKHJhX2MkUGh5bHVtLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKHJhX2MkUGh5bHVtW29yZGVyKHRvdGFsKV0pKQp0bXAgPC0gbWVsdC5kYXRhLnRhYmxlKGRhdGEgPSByYV9jLAogICAgICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMzpuY29sKGNvdW50c19jKSwKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gIlNBTVBMRV9OQU1FIiwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gIlJBIikKCnRtcCA8LSBtZXJnZShkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc21wbCRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgV0VFSyA9IHNtcGwkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc21wbCRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlID0gc21wbCRHZW5vdHlwZSksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IENsYXNzLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDErCiAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgpgYGB7ciBtZWFuc19jLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpscmEgPC0gcmFfbWVsdChyYSA9IHJhX2MsCiAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzbXBsLAogICAgICAgICAgICAgICBzYW1wbGVfbmFtZSA9ICJTQU1QTEVfTkFNRSIpCgptdSA8LSBkYXRhLnRhYmxlKGFnZ3JlZ2F0ZShscmEkUkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChXZWVrID0gbHJhJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBscmEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBscmEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDbGFzcyA9IGxyYSRDbGFzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJDbGFzcyJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIkNsYXNzIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRDbGFzcyA8LSBmYWN0b3IobXUkQ2xhc3MsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJENsYXNzKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDUsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKIyBQQ0EgYXQgQ2xhc3MgbGV2ZWwKYGBge3IgcGNhX2NfcDAsIGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA3fQpkdF9wY2EgPC0gdChyYV9jWywgMzpuY29sKHJhX2MpXSkKY29sbmFtZXMoZHRfcGNhKSA8LSByYV9jJENsYXNzCmR0X3BjYV9jIDwtIGRhdGEudGFibGUoU0FNUExFX05BTUUgPSByb3duYW1lcyhkdF9wY2EpLAogICAgICAgICAgICAgICAgICAgICAgIGR0X3BjYSkKZHRfcGNhX2MgPC0gbWVyZ2Uoc21wbCwKICAgICAgICAgICAgICAgICAgZHRfcGNhX2MsCiAgICAgICAgICAgICAgICAgIGJ5ID0gIlNBTVBMRV9OQU1FIikKCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gVFJVRSwKIyAgICAgICAgICAgICAgc2NhbGUuID0gVFJVRSkKCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gRkFMU0UsCiMgICAgICAgICAgICAgIHNjYWxlLiA9IEZBTFNFKQoKbTEgPC0gcHJjb21wKGR0X3BjYSkKc3VtbWFyeShtMSkKCgojIFNlbGVjdCBQQy1zIHRvIHBsaW90IChQQzEgJiBQQzIpCmNob2ljZXMgPC0gMToyCiMgU2NvcmVzLCBpLmUuIHBvaW50cyAoZGYudSkKZHQuc2NyIDwtIGRhdGEudGFibGUobTEkeFssIGNob2ljZXNdKQojIEFkZCBncm91cGluZyB2YXJpYWJsZQpkdC5zY3IkZ3JwIDwtIHBhc3RlKGR0X3BjYV9jJFRSRUFUTUVOVCwKICAgICAgICAgICAgICAgICAgICBkdF9wY2FfYyRXRUVLLAogICAgICAgICAgICAgICAgICAgIGR0X3BjYV9jJEdlbm90eXBlKQoKZHQuc2NyJFRSRUFUTUVOVCA8LSBkdF9wY2FfYyRUUkVBVE1FTlQKZHQuc2NyJFdFRUsgPC0gZHRfcGNhX2MkV0VFSwpkdC5zY3IkR2Vub3R5cGUgPC0gZHRfcGNhX2MkR2Vub3R5cGUKZHQuc2NyCgojIExvYWRpbmdzLCBpLmUuIGFycm93cyAoZGYudikKZHQucm90IDwtIGFzLmRhdGEuZnJhbWUobTEkcm90YXRpb25bLCBjaG9pY2VzXSkKZHQucm90JGZlYXQgPC0gcm93bmFtZXMoZHQucm90KQpkdC5yb3QgPC0gZGF0YS50YWJsZShkdC5yb3QpCmR0LnJvdAoKZHQubG9hZCA8LSBtZWx0LmRhdGEudGFibGUoZHQucm90LAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gImZlYXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFzdXJlLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAicGMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gImxvYWRpbmciKQpkdC5sb2FkJGZlYXQgPC0gZmFjdG9yKGR0LmxvYWQkZmVhdCwKICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSB1bmlxdWUoZHQubG9hZCRmZWF0KSkKIyBQbG90IGxvYWRpbmdzCnAwIDwtIGdncGxvdChkYXRhID0gZHQubG9hZCwKICAgICAgICAgICAgIGFlcyh4ID0gZmVhdCwKICAgICAgICAgICAgICAgICB5ID0gbG9hZGluZykpICsKICBmYWNldF93cmFwKH4gcGMsCiAgICAgICAgICAgICBucm93ID0gMikgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2d0aXRsZSgiUEMgTG9hZGluZ3MiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQp0aWZmKGZpbGVuYW1lID0gInRtcC9wYy4xLjJfbG9hZGluZ3NfY2xhc3MudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDgsCiAgICAgdW5pdHMgPSAnaW4nLAogICAgIHJlcyA9IDMwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDApCmBgYAoKYGBge3IgcGNhX2F4ZXNfY30KIyBBeGlzIGxhYmVscwp1LmF4aXMubGFicyA8LSBwYXN0ZShjb2xuYW1lcyhkdC5yb3QpWzE6Ml0sIAogICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKCcoJTAuMWYlJSBleHBsYWluZWQgdmFyLiknLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMDAqbTEkc2RldltjaG9pY2VzXV4yL3N1bShtMSRzZGV2XjIpKSkKdS5heGlzLmxhYnMKYGBgCgpgYGB7ciBiaXBsb3RfZ3JwX2MsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KIyB2YXIua2VlcC5uZHggPC0gd2hpY2goZHQucm90JGZlYXQgJWluJSBjKC4uLikpCiMgT3Igc2VsZWN0IGFsbAojIHZhci5rZWVwLm5keCA8LSAzOm5jb2woZHQxKQojIFVzZSBkdC5yb3RbdmFyLmtlZXAubmR4LF0gYW5kIGR0LnJvdCRmZWF0W3Zhci5rZWVwLm5keF0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gZ3JwKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwKICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IDQwKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSA0MCpQQzIpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMS8yLCAncGljYXMnKSksCiAgICAgICAgICAgICAgICMgc2l6ZSA9IDEsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3RleHQoYWVzKHggPSA0NCpQQzEsCiAgICAgICAgICAgICAgICB5ID0gNDQqUEMyLAogICAgICAgICAgICAgICAgbGFiZWwgPSBkdC5yb3QkZmVhdCksCiAgICAgICAgICAgICMgc2l6ZSA9IDUsCiAgICAgICAgICAgIGhqdXN0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHUuYXhpcy5sYWJzWzFdKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHUuYXhpcy5sYWJzWzJdKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkdyb3VwIikgKwogIGdndGl0bGUoIkJpcGxvdCBvZiBDbGFzc2VzIG9mIEJhY3RlcmlhIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMjApKSAKdGlmZihmaWxlbmFtZSA9ICJ0bXAvY2xhc3NfYmlwbG90X2dycC50aWZmIiwKICAgICBoZWlnaHQgPSAxMCwKICAgICB3aWR0aCA9IDEwLAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIGJpcGxvdF9ncnBfd2l0aF9hdmdfYywgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxMH0KIyBGaW5kIGNlbnRlcnMgb2YgZWFjaCBncm91cApncnBnIDwtICJncnAiCnZhcjEgPC0gZXZhbChwYXJzZSh0ZXh0ID0gcGFzdGUoImR0LnNjciQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdycGcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIiIpKSkKCmNudHIgPC0gZGF0YS50YWJsZShHcm91cCA9IHVuaXF1ZSh2YXIxKSwKICAgICAgICAgICAgICAgICAgIFBDMSA9IGFnZ3JlZ2F0ZSh4ID0gZHQuc2NyJFBDMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QodmFyMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSR4LAogICAgICAgICAgICAgICAgICAgUEMyID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdCh2YXIxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCnAyIDwtIHAxICsgZ2VvbV9sYWJlbChkYXRhID0gY250ciwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gUEMxLAogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBQQzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBHcm91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBHcm91cCksCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUoZ3VpZGUgPSBGQUxTRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKcHJpbnQocDIpCmBgYAoKYGBge3IgYmlwbG90X2dlbm90eXBlX2MsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KIyB2YXIua2VlcC5uZHggPC0gd2hpY2goZHQucm90JGZlYXQgJWluJSBjKC4uLikpCiMgT3Igc2VsZWN0IGFsbAojIHZhci5rZWVwLm5keCA8LSAzOm5jb2woZHQxKQojIFVzZSBkdC5yb3RbdmFyLmtlZXAubmR4LF0gYW5kIGR0LnJvdCRmZWF0W3Zhci5rZWVwLm5keF0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gR2Vub3R5cGUpLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLAogICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gNDAqUEMxLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IDQwKlBDMiksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgxLzIsICdwaWNhcycpKSwKICAgICAgICAgICAgICAgIyBzaXplID0gMSwgCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fdGV4dChhZXMoeCA9IDQ0KlBDMSwKICAgICAgICAgICAgICAgIHkgPSA0NCpQQzIsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGR0LnJvdCRmZWF0KSwKICAgICAgICAgICAgIyBzaXplID0gNSwKICAgICAgICAgICAgaGp1c3QgPSAwLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMV0pICsKICBzY2FsZV95X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMl0pICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWUgPSAiR3JvdXAiKSArCiAgZ2d0aXRsZSgiQmlwbG90IG9mIENsYXNzZXMgb2YgQmFjdGVyaWEiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAyMCkpCnRpZmYoZmlsZW5hbWUgPSAidG1wL2NsYXNzX2JpcGxvdF9nZW5vdHlwZS50aWZmIiwKICAgICBoZWlnaHQgPSAxMCwKICAgICB3aWR0aCA9IDEwLAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQpgYGAKCmBgYHtyIGJpcGxvdF9nZW5vdHlwZV93aXRoX2F2Z19jLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIEZpbmQgY2VudGVycyBvZiBlYWNoIGdyb3VwCmdycGcgPC0gIkdlbm90eXBlIgp2YXIxIDwtIGV2YWwocGFyc2UodGV4dCA9IHBhc3RlKCJkdC5zY3IkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncnBnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKSkpCgpjbnRyIDwtIGRhdGEudGFibGUoR3JvdXAgPSB1bmlxdWUodmFyMSksCiAgICAgICAgICAgICAgICAgICBQQzEgPSBhZ2dyZWdhdGUoeCA9IGR0LnNjciRQQzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KHZhcjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikkeCwKICAgICAgICAgICAgICAgICAgIFBDMiA9IGFnZ3JlZ2F0ZSh4ID0gZHQuc2NyJFBDMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QodmFyMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSR4KQpwMiA8LSBwMSArIGdlb21fbGFiZWwoZGF0YSA9IGNudHIsCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gR3JvdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gR3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMykgKwogIHNjYWxlX2NvbG9yX2Rpc2NyZXRlKGd1aWRlID0gRkFMU0UpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCnByaW50KHAyKQpgYGAKCmBgYHtyIGJpcGxvdF93ZWVrX2MsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoID0gMTB9CiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KIyB2YXIua2VlcC5uZHggPC0gd2hpY2goZHQucm90JGZlYXQgJWluJSBjKC4uLikpCiMgT3Igc2VsZWN0IGFsbAojIHZhci5rZWVwLm5keCA8LSAzOm5jb2woZHQxKQojIFVzZSBkdC5yb3RbdmFyLmtlZXAubmR4LF0gYW5kIGR0LnJvdCRmZWF0W3Zhci5rZWVwLm5keF0KcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gV0VFSyksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IDAsCiAgICAgICAgICAgICAgICAgICB5ID0gMCwKICAgICAgICAgICAgICAgICAgIHhlbmQgPSA0MCpQQzEsCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gNDAqUEMyKSwKICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDEvMiwgJ3BpY2FzJykpLAogICAgICAgICAgICAgICAjIHNpemUgPSAxLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gNDQqUEMxLAogICAgICAgICAgICAgICAgeSA9IDQ0KlBDMiwKICAgICAgICAgICAgICAgIGxhYmVsID0gZHQucm90JGZlYXQpLAogICAgICAgICAgICAjIHNpemUgPSA1LAogICAgICAgICAgICBoanVzdCA9IDAuNSkgKwogIHNjYWxlX3hfY29udGludW91cyh1LmF4aXMubGFic1sxXSkgKwogIHNjYWxlX3lfY29udGludW91cyh1LmF4aXMubGFic1syXSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZSA9ICJHcm91cCIpICsKICBnZ3RpdGxlKCJCaXBsb3Qgb2YgQ2xhc3NlcyBvZiBCYWN0ZXJpYSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIwKSkKdGlmZihmaWxlbmFtZSA9ICJ0bXAvY2xhc3NfYmlwbG90X3dlZWsudGlmZiIsCiAgICAgaGVpZ2h0ID0gMTAsCiAgICAgd2lkdGggPSAxMCwKICAgICB1bml0cyA9ICdpbicsCiAgICAgcmVzID0gMzAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBiaXBsb3Rfd2Vla193aXRoX2F2Z19jLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEwfQojIEZpbmQgY2VudGVycyBvZiBlYWNoIGdyb3VwCmdycGcgPC0gIldFRUsiCnZhcjEgPC0gZXZhbChwYXJzZSh0ZXh0ID0gcGFzdGUoImR0LnNjciQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdycGcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIiIpKSkKCmNudHIgPC0gZGF0YS50YWJsZShHcm91cCA9IHVuaXF1ZSh2YXIxKSwKICAgICAgICAgICAgICAgICAgIFBDMSA9IGFnZ3JlZ2F0ZSh4ID0gZHQuc2NyJFBDMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QodmFyMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSR4LAogICAgICAgICAgICAgICAgICAgUEMyID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdCh2YXIxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCnAyIDwtIHAxICsgZ2VvbV9sYWJlbChkYXRhID0gY250ciwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gUEMxLAogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBQQzIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwgPSBHcm91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBHcm91cCksCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUoZ3VpZGUgPSBGQUxTRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKcHJpbnQocDIpCmBgYAoKYGBge3IgYmlwbG90X3RydF9jLCBmaWcuaGVpZ2h0ID0gOCwgZmlnLndpZHRoID0gOH0KIyBCYXNlZCBvbiBGaWd1cmUgcDAsIGtlZXAgb25seSBhIGZldyB2YXJpYWJsZXMgd2l0aCBoaWdoIGxvYWRpbmdzIGluIFBDMSBhbmQgUEMyLS0tLQojIHZhci5rZWVwLm5keCA8LSB3aGljaChkdC5yb3QkZmVhdCAlaW4lIGMoLi4uKSkKIyBPciBzZWxlY3QgYWxsCiMgdmFyLmtlZXAubmR4IDwtIDM6bmNvbChkdDEpCiMgVXNlIGR0LnJvdFt2YXIua2VlcC5uZHgsXSBhbmQgZHQucm90JGZlYXRbdmFyLmtlZXAubmR4XQoKcDEgPC0gZ2dwbG90KGRhdGEgPSBkdC5yb3QsCiAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICB5ID0gUEMyKSkgKwogIGNvb3JkX2VxdWFsKCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGR0LnNjciwKICAgICAgICAgICAgIGFlcyhmaWxsID0gVFJFQVRNRU5UKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC41KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwKICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IDQwKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSA0MCpQQzIpLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMS8yLCAncGljYXMnKSksCiAgICAgICAgICAgICAgICMgc2l6ZSA9IDEsIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX3RleHQoYWVzKHggPSA0NCpQQzEsCiAgICAgICAgICAgICAgICB5ID0gNDQqUEMyLAogICAgICAgICAgICAgICAgbGFiZWwgPSBkdC5yb3QkZmVhdCksCiAgICAgICAgICAgICMgc2l6ZSA9IDUsCiAgICAgICAgICAgIGhqdXN0ID0gMC41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKHUuYXhpcy5sYWJzWzFdKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHUuYXhpcy5sYWJzWzJdKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICJUcmVhdG1lbnQiLAogICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGxldmVscyhkdC5zY3IkVFJFQVRNRU5UKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZ3JlZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvcmFuZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJibHVlIikpICsKICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUoIkJpcGxvdCBvZiBDbGFzc2VzIG9mIEJhY3RlcmlhIikgKwogICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIwKSkKICAgICAgICAgICAgICAgICAgICBnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBiaXBsb3RfdHJ0X3dpdGhfYXZnX2MsIGZpZy5oZWlnaHQgPSA4LCBmaWcud2lkdGggPSA4fQojIEZpbmQgY2VudGVycyBvZiBlYWNoIGdyb3VwCiMgZ3JwZyA8LSAiVFJFQVRNRU5UIgojIHZhcjEgPC0gZXZhbChwYXJzZSh0ZXh0ID0gcGFzdGUoImR0LnNjciQiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JwZywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKSkpCgojIGNudHIgPC0gZGF0YS50YWJsZShHcm91cCA9IGxldmVscyh2YXIxKSwKIyAgICAgICAgICAgICAgICAgICAgUEMxID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMxLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KHZhcjEpLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSR4LAojICAgICAgICAgICAgICAgICAgICBQQzIgPSBhZ2dyZWdhdGUoeCA9IGR0LnNjciRQQzIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QodmFyMSksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCgpjbnRyIDwtIGRhdGEudGFibGUoUEMxID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChkdC5zY3IkVFJFQVRNRU5UKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpLAogICAgICAgICAgICAgICAgICAgUEMyID0gYWdncmVnYXRlKHggPSBkdC5zY3IkUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdCh2YXIxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCmNvbG5hbWVzKGNudHIpIDwtIGMoIlRSRUFUTUVOVCIsCiAgICAgICAgICAgICAgICAgICAgIlBDMSIsCiAgICAgICAgICAgICAgICAgICAgIlBDMiIpCgpwMiA8LSBwMSArIGdlb21fbGFiZWwoZGF0YSA9IGNudHIsCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFBDMSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gUEMyLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IFRSRUFUTUVOVCksCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKGd1aWRlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gbGV2ZWxzKGNudHIkVFJFQVRNRU5UKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZ3JlZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvcmFuZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJibHVlIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgp0aWZmKGZpbGVuYW1lID0gInRtcC9jbGFzc19iaXBsb3RfdHJ0LnRpZmYiLAogICAgIGhlaWdodCA9IDgsCiAgICAgd2lkdGggPSA4LAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMikKZ3JhcGhpY3Mub2ZmKCkKCnByaW50KHAyKQpgYGAKCmBgYHtyIG11bHRpbm9tX2N9CiMgQ292YXJpYXRlcyBvbmx5Cm0xIDwtIG11bHRpbm9tKFRSRUFUTUVOVCB+IFdFRUsgKyBHZW5vdHlwZSwKICAgICAgICAgICAgICAgZGF0YSA9IGR0LnNjcikKc3VtbWFyeShtMSkKCnByZDEgPC0gcHJlZGljdChtMSkKCnQxIDwtIHRhYmxlKFByZWRpY3RlZCA9IHByZDEsCiAgICAgICAgICAgIE9ic2VydmVkID0gZHQuc2NyJFRSRUFUTUVOVCkKCiMgUEMxIGFsb25lCm0yIDwtIG11bHRpbm9tKFRSRUFUTUVOVCB+IFBDMSwKICAgICAgICAgICAgICAgZGF0YSA9IGR0LnNjcikKc3VtbWFyeShtMikKCnByZDIgPC0gcHJlZGljdChtMikKCnQyIDwtIHRhYmxlKFByZWRpY3RlZCA9IHByZDIsCiAgICAgICAgICAgIE9ic2VydmVkID0gZHQuc2NyJFRSRUFUTUVOVCkKCiMgUEMxIHdpdGggY292YXJpYXRlcwptMyA8LSBtdWx0aW5vbShUUkVBVE1FTlQgfiBQQzEgKyBXRUVLICsgR2Vub3R5cGUsCiAgICAgICAgICAgICAgIGRhdGEgPSBkdC5zY3IpCnN1bW1hcnkobTMpCgpwcmQzIDwtIHByZWRpY3QobTMpCgp0MyA8LSB0YWJsZShQcmVkaWN0ZWQgPSBwcmQzLAogICAgICAgICAgICBPYnNlcnZlZCA9IGR0LnNjciRUUkVBVE1FTlQpCgojIFBDMSArIFBDMiB3aXRoIGNvdmFyaWF0ZXMKbTQgPC0gbXVsdGlub20oVFJFQVRNRU5UIH4gUEMxICsgUEMyICsgV0VFSyArIEdlbm90eXBlLAogICAgICAgICAgICAgICBkYXRhID0gZHQuc2NyKQpzdW1tYXJ5KG00KQoKcHJkNCA8LSBwcmVkaWN0KG00KQoKdDQgPC0gdGFibGUoUHJlZGljdGVkID0gcHJkNCwKICAgICAgICAgICAgT2JzZXJ2ZWQgPSBkdC5zY3IkVFJFQVRNRU5UKQoKIyBDb25mdXNpb24gdGFibGVzCmRhdGF0YWJsZShjYmluZCh0MSksIAogICAgICAgICAgY2FwdGlvbiA9ICJDb3ZhcmlhdGVzIE9ubHkiKQpkYXRhdGFibGUoY2JpbmQodDIpLAogICAgICAgICAgY2FwdGlvbiA9ICJQQzEgT25seSIpCmRhdGF0YWJsZShjYmluZCh0MyksCiAgICAgICAgICBjYXB0aW9uID0gIlBDMSB3aXRoIGNvdmFyaWF0ZXMiKQpkYXRhdGFibGUoY2JpbmQodDQpLAogICAgICAgICAgY2FwdGlvbiA9ICJQQzEgKyBQQzIgd2l0aCBjb3ZhcmlhdGVzIikKCiMgQ29tcGFyZSBtb2RlbHMKYW5vdmEobTEsIG0zKQphbm92YShtMiwgbTMpCmFub3ZhKG00LCBtMykKYGBgCgpUaGUgcmVzdWx0cyBzdWdnZXN0IHRoYXQ6ICAKYS4gQ292YXJpYXRlcyBhbG9uZSAodGltZXBvaW50IGFuZCBnZW5vdHlwZSkgY2Fubm90IGV4cGxhaW4gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0cmVhdG1lbnRzLiAgCmIuIFByaW5jaXBhbCBDb21wb25lbnQgMSAoUEMxKSBjYW4gZXhwbGFpbiB0aGUgZGlmZmVyZW5jZXMgaW4gcmVsYXRpdmUgYWJ1bmRhbmNlIG9mIGNsYXNzZXMgaW4gdGhlIHNhbXBsZXMuIFRoZSBtb2RlbCBkb2VzIG5vdCBpbXByb3ZlIHNpZ25pZmljYW50bHkgYnkgYWRkaW5nIHRoZSBjb3ZhcmlhdGVzIG9yIHRoZSBQQzIuIEhvd2V2ZXIsIHRoZSBjb3ZhcmlhdGVzIHNob3VsZCBzdGF5IGluIHRoZSBtb2RlbCBmb3IgYWRqdXN0bWVudCwgYW5kIFBDMiBzbGlnaHRseSBpbXByb3ZlcyB0aGUgcHJlZGljdGlvbnMuICAKYy4gVGhlIGZ1bGwgbW9kZWwgKFBDMSArIFBDMiArIFdlZWsgKyBHZW5vdHlwZSkgY29ycmVjdGx5IGNsYXNzaWZpZXMgMTIgb3V0IG9mIDE4IE5haXZlIHNhbXBsZXMsIGFuZCAxMiBvdXQgb2YgMTggRFNTK0NyYW5idXJyeSBzYW1wbGVzLiAgCiAgCkNvbnRpbnVpbmcgdGhlIHNhbWUgYW5hbHlzaXMgYXQgT3JkZXIsIEZhbWlseSBhbmQgR2VudXMgbGV2ZWxzLgoKRE8gUk9DIEFVQyBORVNUISEhCmBgYHtyIHJvY19GUk9NX0tFQVAxTlJGMl9TVFVEWSwgaGVpZ2h0ID0gNyxmaWcud2lkdGggPSA4fQojICMgT3V0cHV0IHByb2JvYmlsaXRpZXMtLS0tCiMgcHJkMS4xIDwtIHByZWRpY3QobTEsCiMgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJwcm9icyIpCiMgcHJkMS4xIDwtIGRhdGEudGFibGUoSUQgPSBkZi51JElELAojICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGRmLnUkVHJlYXRtZW50LAojICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHByZDEuMSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICA0KSkKIyAKIyBwcmQyLjEgPC0gcHJlZGljdChtMiwKIyAgICAgICAgICAgICAgICAgICB0eXBlID0gInByb2JzIikKIyBwcmQyLjEgPC0gZGF0YS50YWJsZShJRCA9IGRmLnUkSUQsCiMgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gZGYudSRUcmVhdG1lbnQsCiMgICAgICAgICAgICAgICAgICAgICAgcm91bmQocHJkMi4xLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQpKQojIAojICMgU2Vuc2l0aXZpdHkvU3BlY2lmaWNpdHkKIyAjIFRyZXNob2xkcwojIHRyaGQgPC0gc2VxKDAsIDEsIGJ5ID0gMC4wMSkKIyAKIyBvdXQxIDwtIGxpc3QoKQojIGZvciAoaSBpbiAxOmxlbmd0aCh0cmhkKSkgewojICAgdG1wIDwtIGFwcGx5KHByZDEuMVssIC1jKDE6MildLAojICAgICAgICAgICAgICAgIE1BUkdJTiA9IDIsCiMgICAgICAgICAgICAgICAgRlVOID0gZnVuY3Rpb24oYSkgewojICAgICAgICAgICAgICAgICAgcmV0dXJuKGEgPj0gdHJoZFtpXSkKIyAgICAgICAgICAgICAgICB9KQojICAgdG1wMiA8LSBhcHBseShYID0gdG1wLAojICAgICAgICAgICAgICAgICBNQVJHSU4gPSAyLAojICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbihhKSB7CiMgICAgICAgICAgICAgICAgICAgYWdncmVnYXRlKHggPSBhLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QocHJkMS4xJFRyZWF0bWVudCksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9IHN1bSkkeAojICAgICAgICAgICAgICAgICB9KQojICAgdG1wMgojICAgb3V0MVtbaV1dIDwtIGMoc2VucyA9IHN1bShkaWFnKHRtcDIpKS9ucm93KHByZDEuMSksCiMgICAgICAgICAgICAgICAgICBzcGVjID0gKHN1bSh0bXAyW3VwcGVyLnRyaSh0bXAyKV0pICsgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtKHRtcDJbbG93ZXIudHJpKHRtcDIpXSkpLyhucm93KHRtcCkqKG5jb2wodG1wKSAtIDEpKSkKIyB9CiMgb3V0MSA8LSBkYXRhLnRhYmxlKGRvLmNhbGwoInJiaW5kIiwgb3V0MSkpCiMgb3V0MSA8LSB1bmlxdWUob3V0MSkKIyAKIyBvdXQyIDwtIGxpc3QoKQojIGZvciAoaSBpbiAxOmxlbmd0aCh0cmhkKSkgewojICAgdG1wIDwtIGFwcGx5KHByZDIuMVssIC1jKDE6MildLAojICAgICAgICAgICAgICAgIE1BUkdJTiA9IDIsCiMgICAgICAgICAgICAgICAgRlVOID0gZnVuY3Rpb24oYSkgewojICAgICAgICAgICAgICAgICAgcmV0dXJuKGEgPj0gdHJoZFtpXSkKIyAgICAgICAgICAgICAgICB9KQojICAgdG1wMiA8LSBhcHBseShYID0gdG1wLAojICAgICAgICAgICAgICAgICBNQVJHSU4gPSAyLAojICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbihhKSB7CiMgICAgICAgICAgICAgICAgICAgYWdncmVnYXRlKHggPSBhLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QocHJkMi4xJFRyZWF0bWVudCksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9IHN1bSkkeAojICAgICAgICAgICAgICAgICB9KQojICAgb3V0MltbaV1dIDwtIGMoc2VucyA9IHN1bShkaWFnKHRtcDIpKS9ucm93KHByZDIuMSksCiMgICAgICAgICAgICAgICAgICBzcGVjID0gKHN1bSh0bXAyW3VwcGVyLnRyaSh0bXAyKV0pICsgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtKHRtcDJbbG93ZXIudHJpKHRtcDIpXSkpLyhucm93KHRtcCkqKG5jb2wodG1wKSAtIDEpKSkKIyB9CiMgb3V0MiA8LSBkYXRhLnRhYmxlKGRvLmNhbGwoInJiaW5kIiwgb3V0MikpCiMgb3V0MiA8LSB1bmlxdWUob3V0MikKIyAKIyAjIFJPQwojIHJvYzEgPC0gYXVjKHggPSBvdXQxJHNwZWMsCiMgICAgICAgICAgICAgeSA9IG91dDEkc2VucywKIyAgICAgICAgICAgICBmcm9tID0gMCwKIyAgICAgICAgICAgICB0byA9IDEpCiMgCiMgcm9jMiA8LSBhdWMoeCA9IG91dDIkc3BlYywKIyAgICAgICAgICAgICB5ID0gb3V0MiRzZW5zLAojICAgICAgICAgICAgIGZyb20gPSAwLAojICAgICAgICAgICAgIHRvID0gMSkKIyAKIyAjIFJPQyBwbG90CiMgcGxvdChvdXQxJHNlbnMgfiBvdXQxJHNwZWMsCiMgICAgICB0eXBlID0gImwiLAojICAgICAgeGxpbSA9IGMoMCwgMSksCiMgICAgICB5bGltID0gYygwLCAxKSwKIyAgICAgIHhsYWIgPSAiMSAtIFNwZWNpZmljaXR5IiwKIyAgICAgIHlsYWIgPSAiU2Vuc2l0aXZpdHkiLAojICAgICAgY29sID0gImJsdWUiKQojIGxpbmVzKG91dDIkc2VucyB+IG91dDIkc3BlYywKIyAgICAgICBjb2wgPSAicmVkIikKIyB0ZXh0KHggPSBjKDAuOCwgMC44KSwKIyAgICAgIHkgPSBjKDAuMiwgMC4zKSwKIyAgICAgIGxhYmVsID0gYyhwYXN0ZSgiUk9DKFBDMSkgPSAiLAojICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJvYzEsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgIDMpKSwKIyAgICAgICAgICAgICAgICBwYXN0ZSgiXG5ST0MoUEMxK1BDMikgPSAiLAojICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJvYzIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgMykpKSwKIyAgICAgIGNvbCA9IGMoImJsdWUiLAojICAgICAgICAgICAgICAicmVkIikpCiMgYWJsaW5lKDAsIDEsIGx0eSA9IDIpCmBgYAoKYGBge3IgbWVhbnNfY19wMCwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDd9Cm11JFRydF9HZW5vdHlwZSA8LSBmYWN0b3IocGFzdGUobXUkVHJlYXRtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgIG11JEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikpCgpwMCA8LSBnZ3Bsb3QobXUsCiAgICAgICAgICAgICBhZXMoeCA9IFdlZWssCiAgICAgICAgICAgICAgICAgeSA9IHgsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUcnRfR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IENsYXNzLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV95IikgKwogIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gVHJ0X0dlbm90eXBlKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41LAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9jbGFzc19vdmVyX3RpbWUudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDcsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDApCmBgYAoKYGBge3IgbWVhbnNfY19wMSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDl9CnAxIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gQ2xhc3MsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcnRfR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgc2hhcGUgPSBXZWVrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9jbGFzc19yYS50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpgYGAKCiMjIDIuIE9yZGVyCmBgYHtyIGNvdW50c19vLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0xNX0KY291bnRzX28gPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIk9yZGVyIikKcmFfbyA8LSByYV9ieV90YXhfcmFuayhjb3VudHNfbykKCnRheC5yYW5rcyA8LSB1bmlxdWUob3R1MVssIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9yZGVyIildKQoKcmFfbyA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfbywKICAgICAgICAgICAgICBieSA9ICJPcmRlciIpCgp0b3RhbCA8LSByb3dTdW1zKHJhX29bLCAzOm5jb2wocmFfbyldKQoKcmFfbyRPcmRlciA8LSBmYWN0b3IocmFfbyRPcmRlciwKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfbyRPcmRlcltvcmRlcih0b3RhbCldKQoKcmFfbyRQaHlsdW0gPC0gZmFjdG9yKHJhX28kUGh5bHVtLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKHJhX28kUGh5bHVtW29yZGVyKHRvdGFsKV0pKQp0bXAgPC0gbWVsdC5kYXRhLnRhYmxlKGRhdGEgPSByYV9vLAogICAgICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMzpuY29sKGNvdW50c19vKSwKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gIlNBTVBMRV9OQU1FIiwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gIlJBIikKCnRtcCA8LSBtZXJnZShkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc21wbCRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgV0VFSyA9IHNtcGwkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc21wbCRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlID0gc21wbCRHZW5vdHlwZSksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IE9yZGVyLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDErCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgpgYGB7ciBtZWFuc19vLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpscmEgPC0gcmFfbWVsdChyYSA9IHJhX28sCiAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzbXBsLAogICAgICAgICAgICAgICBzYW1wbGVfbmFtZSA9ICJTQU1QTEVfTkFNRSIpCgptdSA8LSBkYXRhLnRhYmxlKGFnZ3JlZ2F0ZShscmEkUkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChXZWVrID0gbHJhJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBscmEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBscmEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPcmRlciA9IGxyYSRPcmRlciksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJPcmRlciJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIk9yZGVyIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRPcmRlciA8LSBmYWN0b3IobXUkT3JkZXIsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJE9yZGVyKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDUsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKYGBge3IgbWVhbnNfb19wMCwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDd9Cm11JFRydF9HZW5vdHlwZSA8LSBmYWN0b3IocGFzdGUobXUkVHJlYXRtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11JEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikpCgpwMCA8LSBnZ3Bsb3QobXUsCiAgICAgICAgICAgICBhZXMoeCA9IFdlZWssCiAgICAgICAgICAgICAgICAgeSA9IHgsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUcnRfR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IE9yZGVyLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV95IikgKwogIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gVHJ0X0dlbm90eXBlKSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIGFscGhhID0gMC41LAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpCgp0aWZmKGZpbGVuYW1lID0gInRtcC93dF9PcmRlcl9vdmVyX3RpbWUudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDcsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDApCmBgYAoKYGBge3IgbWVhbnNfb19wMSwgZmlnLmhlaWdodCA9IDcsIGZpZy53aWR0aCA9IDd9CnAxIDwtIGdncGxvdChtdSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gT3JkZXIsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcnRfR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgc2hhcGUgPSBXZWVrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X09yZGVyX3JhLnRpZmYiLAogICAgIGhlaWdodCA9IDQsCiAgICAgd2lkdGggPSA3LAogICAgIHVuaXRzID0gImluIiwKICAgICByZXMgPSA2MDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxICsKICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpgYGAKCiMjIDMuIEZhbWlseQpgYGB7ciBjb3VudHNfZiwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsZmlnLndpZHRoPTE1LGZpZy5oZWlnaHQ9MTV9CmNvdW50c19mIDwtIGNvdW50c19ieV90YXhfcmFuayhkdDEgPSBvdHUxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdncl9ieSA9ICJGYW1pbHkiKQpyYV9mIDwtIHJhX2J5X3RheF9yYW5rKGNvdW50c19mKQoKdGF4LnJhbmtzIDwtIHVuaXF1ZShvdHUxWywgYygiUGh5bHVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFtaWx5IildKQoKcmFfZiA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfZiwKICAgICAgICAgICAgICBieSA9ICJGYW1pbHkiKQoKdG90YWwgPC0gcm93U3VtcyhyYV9mWywgMzpuY29sKHJhX2YpXSkKCnJhX2YkRmFtaWx5IDwtIGZhY3RvcihyYV9mJEZhbWlseSwKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfZiRGYW1pbHlbb3JkZXIodG90YWwpXSkKCnJhX2YkUGh5bHVtIDwtIGZhY3RvcihyYV9mJFBoeWx1bSwKICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHVuaXF1ZShyYV9mJFBoeWx1bVtvcmRlcih0b3RhbCldKSkKdG1wIDwtIG1lbHQuZGF0YS50YWJsZShkYXRhID0gcmFfZiwKICAgICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUudmFycyA9IDM6bmNvbChjb3VudHNfZiksCiAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUubmFtZSA9ICJTQU1QTEVfTkFNRSIsCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJSQSIpCgp0bXAgPC0gbWVyZ2UoZGF0YS50YWJsZShTQU1QTEVfTkFNRSA9IHNtcGwkU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgICAgICAgIFdFRUsgPSBzbXBsJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgIFRSRUFUTUVOVCA9IHNtcGwkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICBHZW5vdHlwZSA9IHNtcGwkR2Vub3R5cGUpLAogICAgICAgICAgICAgdG1wLAogICAgICAgICAgICAgYnkgPSAiU0FNUExFX05BTUUiKQoKIyBQbG90IHNhbXBsZXMKcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgIGFlcyh4ID0gU0FNUExFX05BTUUsCiAgICAgICAgICAgICAgICAgeSA9IFJBLAogICAgICAgICAgICAgICAgIGZpbGwgPSBGYW1pbHksCiAgICAgICAgICAgICAgICAgY29sb3IgPSBQaHlsdW0pKSArCiAgZmFjZXRfd3JhcCh+IFdFRUsgKyBUUkVBVE1FTlQgKyBHZW5vdHlwZSwKICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlX3giLAogICAgICAgICAgICAgbnJvdyA9IDMpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQpnZ3Bsb3RseShwMSsKICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpgYGAKCmBgYHtyIG1lYW5zX2YsIGVjaG8gPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0V9CmxyYSA8LSByYV9tZWx0KHJhID0gcmFfZiwKICAgICAgICAgICAgICAgc2FtcGxlcyA9IHNtcGwsCiAgICAgICAgICAgICAgIHNhbXBsZV9uYW1lID0gIlNBTVBMRV9OQU1FIikKCm11IDwtIGRhdGEudGFibGUoYWdncmVnYXRlKGxyYSRSQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KFdlZWsgPSBscmEkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGxyYSRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5vdHlwZSA9IGxyYSRHZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZhbWlseSA9IGxyYSRGYW1pbHkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpKQptdVssIHRvdGFsIDo9IHN1bSh4KSwKICAgYnkgPSAiRmFtaWx5Il0KdWwgPC0gdW5pcXVlKG11WywgYygiRmFtaWx5IiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRGYW1pbHkgPC0gZmFjdG9yKG11JEZhbWlseSwKICAgICAgICAgICAgICAgICAgIGxldmVsID0gdWwkRmFtaWx5KQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIEZhbWlseSA9IGxpc3QobGlzdCgzLCAnZGVzYycpKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSA1LAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKCk5PVEU6IG9ubHkgdGhlIGZpcnN0IDI0IGZhbWlsaWVzIGhhZCBsYXJnZSBlbm91Z2ggY291bnRzIC0gcGxvdGluZyBvbmx5IHRoZW0uICAKICAKYGBge3IgbWVhbnNfZl9wMCwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDd9Cm11JFRydF9HZW5vdHlwZSA8LSBmYWN0b3IocGFzdGUobXUkVHJlYXRtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11JEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikpCm11MSA8LSBkcm9wbGV2ZWxzKG11W0ZhbWlseSAlaW4lIGxldmVscyhtdSRGYW1pbHkpW25sZXZlbHMobXUkRmFtaWx5KToobmxldmVscyhtdSRGYW1pbHkpIC0gMjQpXSwgXSkKCnAwIDwtIGdncGxvdChtdTEsCiAgICAgICAgICAgICBhZXMoeCA9IFdlZWssCiAgICAgICAgICAgICAgICAgeSA9IHgsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPSBUcnRfR2Vub3R5cGUpKSArCiAgZmFjZXRfd3JhcCh+IEZhbWlseSwKICAgICAgICAgICAgIHNjYWxlID0gImZyZWVfeSIpICsKICBnZW9tX2xpbmUocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IFRydF9HZW5vdHlwZSksCiAgICAgICAgICAgICBzaGFwZSA9IDIxLAogICAgICAgICAgICAgc2l6ZSA9IDIsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIlJlbGF0aXZlIEFidW5kYW5jZSAoJSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3RfRmFtaWx5X292ZXJfdGltZS50aWZmIiwKICAgICBoZWlnaHQgPSA3LAogICAgIHdpZHRoID0gOSwKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDApCmdyYXBoaWNzLm9mZigpCgpwcmludChwMCkKYGBgCgpgYGB7ciBtZWFuc19mX3AxLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gOX0KcDEgPC0gZ2dwbG90KG11MSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gRmFtaWx5LAogICAgICAgICAgICAgICAgIGNvbG9yID0gVHJ0X0dlbm90eXBlLAogICAgICAgICAgICAgICAgIHNoYXBlID0gV2VlaykpICsKICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxLAogICAgICAgICAgICAgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIHNjYWxlX3hfY29udGludW91cygiUmVsYXRpdmUgQWJ1bmRhbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X0ZhbWlseV9yYS50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNywKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSsKICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpgYGAKCiMjIDQuIEdlbnVzCmBgYHtyIGNvdW50c19nLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0xNX0KY291bnRzX2cgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dTEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIkdlbnVzIikKcmFfZyA8LSByYV9ieV90YXhfcmFuayhjb3VudHNfZykKCnRheC5yYW5rcyA8LSB1bmlxdWUob3R1MVssIGMoIlBoeWx1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdlbnVzIildKQoKcmFfZyA8LSBtZXJnZSh0YXgucmFua3MsCiAgICAgICAgICAgICAgcmFfZywKICAgICAgICAgICAgICBieSA9ICJHZW51cyIpCgp0b3RhbCA8LSByb3dTdW1zKHJhX2dbLCAzOm5jb2wocmFfZyldKQoKcmFfZyRHZW51cyA8LSBmYWN0b3IocmFfZyRHZW51cywKICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gcmFfZyRHZW51c1tvcmRlcih0b3RhbCldKQoKcmFfZyRQaHlsdW0gPC0gZmFjdG9yKHJhX2ckUGh5bHVtLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKHJhX2ckUGh5bHVtW29yZGVyKHRvdGFsKV0pKQp0bXAgPC0gbWVsdC5kYXRhLnRhYmxlKGRhdGEgPSByYV9nLAogICAgICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSAxOjIsCiAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMzpuY29sKGNvdW50c19nKSwKICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gIlNBTVBMRV9OQU1FIiwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gIlJBIikKCnRtcCA8LSBtZXJnZShkYXRhLnRhYmxlKFNBTVBMRV9OQU1FID0gc21wbCRTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICAgICAgICAgV0VFSyA9IHNtcGwkV0VFSywKICAgICAgICAgICAgICAgICAgICAgICAgVFJFQVRNRU5UID0gc21wbCRUUkVBVE1FTlQsCiAgICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlID0gc21wbCRHZW5vdHlwZSksCiAgICAgICAgICAgICB0bXAsCiAgICAgICAgICAgICBieSA9ICJTQU1QTEVfTkFNRSIpCgojIFBsb3Qgc2FtcGxlcwpwMSA8LSBnZ3Bsb3QodG1wLAogICAgICAgICAgICAgYWVzKHggPSBTQU1QTEVfTkFNRSwKICAgICAgICAgICAgICAgICB5ID0gUkEsCiAgICAgICAgICAgICAgICAgZmlsbCA9IEdlbnVzLAogICAgICAgICAgICAgICAgIGNvbG9yID0gUGh5bHVtKSkgKwogIGZhY2V0X3dyYXAofiBXRUVLICsgVFJFQVRNRU5UICsgR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZV94IiwKICAgICAgICAgICAgIG5yb3cgPSAzKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKZ2dwbG90bHkocDErCiAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgpgYGB7ciBtZWFuc19nLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpscmEgPC0gcmFfbWVsdChyYSA9IHJhX2csCiAgICAgICAgICAgICAgIHNhbXBsZXMgPSBzbXBsLAogICAgICAgICAgICAgICBzYW1wbGVfbmFtZSA9ICJTQU1QTEVfTkFNRSIpCgptdSA8LSBkYXRhLnRhYmxlKGFnZ3JlZ2F0ZShscmEkUkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gbGlzdChXZWVrID0gbHJhJFdFRUssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmVhdG1lbnQgPSBscmEkVFJFQVRNRU5ULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2Vub3R5cGUgPSBscmEkR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW51cyA9IGxyYSRHZW51cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZVTiA9ICJtZWFuIikpCm11WywgdG90YWwgOj0gc3VtKHgpLAogICBieSA9ICJHZW51cyJdCnVsIDwtIHVuaXF1ZShtdVssIGMoIkdlbnVzIiwgCiAgICAgICAgICAgICAgICAgICAgInRvdGFsIildKQp1bCA8LSB1bFtvcmRlcih0b3RhbCksXQptdSRHZW51cyA8LSBmYWN0b3IobXUkR2VudXMsCiAgICAgICAgICAgICAgICAgICBsZXZlbCA9IHVsJEdlbnVzKQptdSR0b3RhbCA8LSBOVUxMCgpkYXRhdGFibGUobXUsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgIEdlbnVzID0gbGlzdChsaXN0KDMsICdkZXNjJykpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDUsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKYGBge3IgbWVhbnNfZ19wMCwgZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDd9Cm11JFRydF9HZW5vdHlwZSA8LSBmYWN0b3IocGFzdGUobXUkVHJlYXRtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11JEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICJfIikpCm11MSA8LSBkcm9wbGV2ZWxzKG11W0dlbnVzICVpbiUgbGV2ZWxzKG11JEdlbnVzKVtubGV2ZWxzKG11JEdlbnVzKToobmxldmVscyhtdSRHZW51cykgLSAzNSldLCBdKQoKcDAgPC0gZ2dwbG90KG11MSwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0geCwKICAgICAgICAgICAgICAgICBncm91cCA9IFRydF9HZW5vdHlwZSkpICsKICBmYWNldF93cmFwKH4gR2VudXMsCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3kiKSArCiAgZ2VvbV9saW5lKHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBUcnRfR2Vub3R5cGUpLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHNpemUgPSAyLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3d0X0dlbnVzX292ZXJfdGltZS50aWZmIiwKICAgICBoZWlnaHQgPSA5LAogICAgIHdpZHRoID0gMTIsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDArCiAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgpgYGB7ciBtZWFuc19nX3AxLCBmaWcuaGVpZ2h0ID0gOSwgZmlnLndpZHRoID0gOX0KcDEgPC0gZ2dwbG90KG11MSwKICAgICAgICAgICAgIGFlcyh4ID0geCwKICAgICAgICAgICAgICAgICB5ID0gR2VudXMsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBUcnRfR2Vub3R5cGUsCiAgICAgICAgICAgICAgICAgc2hhcGUgPSBXZWVrKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKCJSZWxhdGl2ZSBBYnVuZGFuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvd3RfR2VudXNfcmEudGlmZiIsCiAgICAgaGVpZ2h0ID0gOSwKICAgICB3aWR0aCA9IDksCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQoKZ2dwbG90bHkocDErCiAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKYGBgCgojIFNlc3Npb24gSW5mb3JtYXRpb24KYGBge3IgaW5mbyxldmFsPVRSVUV9CnNlc3Npb25JbmZvKCkKYGBg